From b736ee0bc29aa407658752e0353462e807f85aaa Mon Sep 17 00:00:00 2001 From: mdfkbtc Date: Mon, 30 Mar 2020 19:21:42 +0200 Subject: [PATCH] Integrate and configure Eslint, beautify code, update some packages --- .eslintrc | 87 +- App.js | 198 +- BlueApp.js | 29 +- BlueComponents.js | 4332 +++++++++-------- BlueElectrum.js | 283 +- MainBottomTabs.js | 212 +- MockStorage.js | 16 +- NavigationService.js | 8 +- Privacy.js | 15 +- UnlockWith.js | 192 +- WatchConnectivity.android.js | 6 +- WatchConnectivity.ios.js | 134 +- analytics.js | 26 +- appcenter-post-build-get-pr-number.js | 32 +- babel.config.js | 2 +- class/abstract-hd-wallet.js | 92 +- class/abstract-wallet.js | 28 +- class/app-storage.js | 189 +- class/biometrics.js | 15 +- class/hd-legacy-p2pkh-wallet.js | 58 +- class/hd-segwit-bech32-transaction.js | 153 +- class/hd-segwit-bech32-wallet.js | 121 +- class/hd-segwit-p2sh-wallet.js | 68 +- class/index.js | 24 +- class/legacy-wallet.js | 136 +- class/onAppLaunch.js | 25 +- class/quickActions.js | 22 +- class/segwit-bech-wallet.js | 21 +- class/segwit-p2sh-wallet.js | 43 +- class/walletGradient.js | 26 +- class/watch-only-wallet.js | 88 +- currency.js | 101 +- encryption.js | 6 +- events.js | 25 +- index.js | 40 +- loc/ZAR_Afr.js | 367 +- loc/ZAR_Xho.js | 368 +- loc/cs_CZ.js | 383 +- loc/da_DK.js | 385 +- loc/de_DE.js | 386 +- loc/el.js | 389 +- loc/en.js | 102 +- loc/es.js | 109 +- loc/fi_FI.js | 384 +- loc/fr_FR.js | 381 +- loc/hr_HR.js | 383 +- loc/hu_HU.js | 383 +- loc/id_ID.js | 382 +- loc/index.js | 222 +- loc/it.js | 378 +- loc/jp_JP.js | 103 +- loc/ko_KR.js | 100 +- loc/nb_NO.js | 387 +- loc/nl_NL.js | 387 +- loc/pt_BR.js | 396 +- loc/pt_PT.js | 393 +- loc/ru.js | 389 +- loc/sv_SE.js | 382 +- loc/th_TH.js | 388 +- loc/tr_TR.js | 380 +- loc/ua.js | 385 +- loc/vi_VN.js | 112 +- loc/zh_cn.js | 69 +- loc/zh_tw.js | 370 +- models/bitcoinTransactionInfo.js | 2 +- models/bitcoinUnits.js | 12 +- models/fiatUnit.js | 50 +- models/networkTransactionFees.js | 29 +- models/signer.js | 221 +- package-lock.json | 1466 +++++- package.json | 23 +- prompt.js | 28 +- react-native.config.js | 20 +- screen/plausibledeniability.js | 57 +- screen/receive/details.js | 114 +- screen/receive/receiveAmount.js | 112 +- screen/selftest.js | 270 +- screen/send/confirm.js | 190 +- screen/send/create.js | 174 +- screen/send/details.js | 828 +++- screen/send/psbtWithHardwareWallet.js | 208 +- screen/send/scanQrAddress.js | 92 +- screen/send/success.js | 82 +- screen/settings/about.js | 77 +- screen/settings/currency.js | 65 +- screen/settings/defaultView.js | 48 +- screen/settings/electrumSettings.js | 112 +- screen/settings/encryptStorage.js | 62 +- screen/settings/language.js | 99 +- screen/settings/releasenotes.js | 28 +- screen/settings/settings.js | 100 +- screen/transactions/CPFP.js | 192 +- screen/transactions/RBF-create.js | 162 +- screen/transactions/RBF.js | 128 +- screen/transactions/RBFBumpFee.js | 71 +- screen/transactions/RBFCancel.js | 72 +- screen/transactions/details.js | 303 +- screen/transactions/transactionStatus.js | 292 +- screen/wallets/add.js | 156 +- screen/wallets/buyBitcoin.js | 49 +- screen/wallets/details.js | 218 +- screen/wallets/export.js | 77 +- screen/wallets/import.js | 128 +- screen/wallets/list.js | 191 +- screen/wallets/marketplace.js | 47 +- screen/wallets/pleaseBackup.js | 290 +- screen/wallets/reorderWallets.js | 104 +- screen/wallets/scanQrWif.js | 220 +- screen/wallets/selectWallet.js | 132 +- screen/wallets/transactions.js | 237 +- screen/wallets/walletMigrate.js | 95 +- screen/wallets/xpub.js | 62 +- shim.js | 25 +- tests/integration/App.test.js | 192 +- tests/integration/Bip38.test.js | 40 +- tests/integration/Electrum.test.js | 281 +- tests/integration/HDWallet.test.js | 474 +- .../LightningCustodianWallet.test.js | 227 +- tests/integration/Loc.test.js | 36 +- tests/integration/Storage.test.js | 74 +- tests/integration/WatchOnlyWallet.test.js | 134 +- .../hd-segwit-bech32-transaction.test.js | 165 +- .../hd-segwit-bech32-wallet.test.js | 316 +- up-build-number.js | 11 +- 124 files changed, 15388 insertions(+), 10478 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4bf98c890da..12266cd5c2c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,21 +1,76 @@ { - "parser": "babel-eslint", + "env": { + "jest": true, + "react-native/react-native": true + }, + "extends": [ + "eslint:recommended", + "plugin:react/recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:import/typescript", + "prettier", + "prettier/react" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "2019", + "sourceType": "module", + "ecmaFeatures": { + "jsx": true + } + }, "plugins": [ - "react", "prettier" + "@typescript-eslint", + "react", + "react-native", + "react-hooks", + "import", + "prettier" ], - "extends": ["standard", "standard-react", "prettier"], - "rules": { - 'prettier/prettier': [ - 'warn', - { - singleQuote: true, - printWidth: 140, - trailingComma: 'all' + "settings": { + "react": { + "version": "detect" + }, + "import/resolver": { + "node": { + "extensions": [".js", ".jsx", ".ts", ".tsx"] } - ] - }, - "env":{ - "es6": true + } }, - "globals": { "fetch": false } -} + "rules": { + "@typescript-eslint/camelcase": "off", + "@typescript-eslint/class-name-casing": "warn", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/member-delimiter-style": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-ignore": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/indent": "off", + "@typescript-eslint/no-var-requires": "warn", + "@typescript-eslint/no-this-alias": "warn", + "@typescript-eslint/no-empty-function": "warn", + "no-async-promise-executor": "warn", + "no-case-declarations": "off", + "no-prototype-builtins": "off", + "no-empty": ["error", { "allowEmptyCatch": true }], + "no-undef": "warn", + "no-redeclare": "warn", + "no-var": "warn", + "require-atomic-updates": "off", + "prettier/prettier": "error", + "prefer-const": "warn", + "react/display-name": "off", + "react/prop-types": "warn", + "react/no-unescaped-entities": "warn", + "react-hooks/rules-of-hooks": "error", + "react-hooks/exhaustive-deps": "warn", + "react-native/no-color-literals": "warn", + "react-native/no-raw-text": "warn", + "react-native/no-single-element-style-arrays": "warn", + "react-native/no-unused-styles": "warn", + "import/newline-after-import": "error", + "import/no-duplicates": "error" + } +} \ No newline at end of file diff --git a/App.js b/App.js index 48325bfa626..421b34ea8a1 100644 --- a/App.js +++ b/App.js @@ -1,31 +1,42 @@ -import React from 'react'; -import { Linking, DeviceEventEmitter, AppState, Clipboard, StyleSheet, KeyboardAvoidingView, Platform, View } from 'react-native'; -import AsyncStorage from '@react-native-community/async-storage'; -import Modal from 'react-native-modal'; -import { NavigationActions } from 'react-navigation'; -import MainBottomTabs from './MainBottomTabs'; -import NavigationService from './NavigationService'; -import { BlueTextCentered, BlueButton } from './BlueComponents'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import url from 'url'; -import { AppStorage } from './class'; -import { Chain } from './models/bitcoinUnits'; -import QuickActions from 'react-native-quick-actions'; -import * as Sentry from '@sentry/react-native'; -import OnAppLaunch from './class/onAppLaunch'; -const A = require('./analytics'); +import React from "react"; +import { + Linking, + DeviceEventEmitter, + AppState, + Clipboard, + StyleSheet, + KeyboardAvoidingView, + Platform, + View +} from "react-native"; +import AsyncStorage from "@react-native-community/async-storage"; +import Modal from "react-native-modal"; +import { NavigationActions } from "react-navigation"; +import MainBottomTabs from "./MainBottomTabs"; +import NavigationService from "./NavigationService"; +import { BlueTextCentered, BlueButton } from "./BlueComponents"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import url from "url"; +import { AppStorage } from "./class"; +import { Chain } from "./models/bitcoinUnits"; +import QuickActions from "react-native-quick-actions"; +import * as Sentry from "@sentry/react-native"; +import OnAppLaunch from "./class/onAppLaunch"; -if (process.env.NODE_ENV !== 'development') { +const A = require("./analytics"); + +if (process.env.NODE_ENV !== "development") { Sentry.init({ - dsn: 'https://23377936131848ca8003448a893cb622@sentry.io/1295736', + dsn: "https://23377936131848ca8003448a893cb622@sentry.io/1295736" }); } -const bitcoin = require('bitcoinjs-lib'); -const bitcoinModalString = 'Bitcoin address'; -const loc = require('./loc'); +const bitcoin = require("bitcoinjs-lib"); + +const bitcoinModalString = "Bitcoin address"; +const loc = require("./loc"); /** @type {AppStorage} */ -const BlueApp = require('./BlueApp'); +const BlueApp = require("./BlueApp"); export default class App extends React.Component { navigator = null; @@ -34,29 +45,34 @@ export default class App extends React.Component { appState: AppState.currentState, isClipboardContentModalVisible: false, clipboardContentModalAddressType: bitcoinModalString, - clipboardContent: '', + clipboardContent: "" }; async componentDidMount() { - Linking.addEventListener('url', this.handleOpenURL); - AppState.addEventListener('change', this._handleAppStateChange); + Linking.addEventListener("url", this.handleOpenURL); + AppState.addEventListener("change", this._handleAppStateChange); QuickActions.popInitialAction().then(this.popInitialAction); - DeviceEventEmitter.addListener('quickActionShortcut', this.walletQuickActions); + DeviceEventEmitter.addListener( + "quickActionShortcut", + this.walletQuickActions + ); } popInitialAction = async data => { if (data) { // eslint-disable-next-line no-unused-expressions this.navigator.dismiss; - const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === data.userInfo.url.split('wallet/')[1]); + const wallet = BlueApp.getWallets().find( + wallet => wallet.getID() === data.userInfo.url.split("wallet/")[1] + ); this.navigator.dispatch( NavigationActions.navigate({ key: `WalletTransactions-${wallet.getID()}`, - routeName: 'WalletTransactions', + routeName: "WalletTransactions", params: { - wallet, - }, - }), + wallet + } + }) ); } else { const url = await Linking.getInitialURL(); @@ -70,16 +86,18 @@ export default class App extends React.Component { // eslint-disable-next-line no-unused-expressions this.navigator.dismiss; const selectedDefaultWallet = await OnAppLaunch.getSelectedDefaultWallet(); - const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === selectedDefaultWallet.getID()); + const wallet = BlueApp.getWallets().find( + wallet => wallet.getID() === selectedDefaultWallet.getID() + ); if (wallet) { this.navigator.dispatch( NavigationActions.navigate({ - routeName: 'WalletTransactions', + routeName: "WalletTransactions", key: `WalletTransactions-${wallet.getID()}`, params: { - wallet, - }, - }), + wallet + } + }) ); } } @@ -88,37 +106,44 @@ export default class App extends React.Component { }; walletQuickActions = data => { - const wallet = BlueApp.getWallets().find(wallet => wallet.getID() === data.userInfo.url.split('wallet/')[1]); + const wallet = BlueApp.getWallets().find( + wallet => wallet.getID() === data.userInfo.url.split("wallet/")[1] + ); // eslint-disable-next-line no-unused-expressions this.navigator.dismiss; this.navigator.dispatch( NavigationActions.navigate({ - routeName: 'WalletTransactions', + routeName: "WalletTransactions", key: `WalletTransactions-${wallet.getID()}`, params: { - wallet, - }, - }), + wallet + } + }) ); }; componentWillUnmount() { - Linking.removeEventListener('url', this.handleOpenURL); - AppState.removeEventListener('change', this._handleAppStateChange); + Linking.removeEventListener("url", this.handleOpenURL); + AppState.removeEventListener("change", this._handleAppStateChange); } _handleAppStateChange = async nextAppState => { if (BlueApp.getWallets().length > 0) { - if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') { + if ( + this.state.appState.match(/inactive|background/) && + nextAppState === "active" + ) { A(A.ENUM.APP_UNSUSPENDED); const clipboard = await Clipboard.getString(); const isAddressFromStoredWallet = BlueApp.getWallets().some(wallet => - wallet.chain === Chain.ONCHAIN ? wallet.weOwnAddress(clipboard) : wallet.isInvoiceGeneratedByWallet(clipboard), + wallet.chain === Chain.ONCHAIN + ? wallet.weOwnAddress(clipboard) + : wallet.isInvoiceGeneratedByWallet(clipboard) ); if ( !isAddressFromStoredWallet && this.state.clipboardContent !== clipboard && - (this.isBitcoinAddress(clipboard)) + this.isBitcoinAddress(clipboard) ) { this.setState({ isClipboardContentModalVisible: true }); } @@ -129,13 +154,14 @@ export default class App extends React.Component { }; hasSchema(schemaString) { - if (typeof schemaString !== 'string' || schemaString.length <= 0) return false; + if (typeof schemaString !== "string" || schemaString.length <= 0) + return false; const lowercaseString = schemaString.trim().toLowerCase(); return ( - lowercaseString.startsWith('bitcoin:') || - lowercaseString.startsWith('blue:') || - lowercaseString.startsWith('bluewallet:') || - lowercaseString.startsWith('lapp:') + lowercaseString.startsWith("bitcoin:") || + lowercaseString.startsWith("blue:") || + lowercaseString.startsWith("bluewallet:") || + lowercaseString.startsWith("lapp:") ); } @@ -149,7 +175,10 @@ export default class App extends React.Component { isValidBitcoinAddress = false; } if (!isValidBitcoinAddress) { - if (address.indexOf('bitcoin:') === 0 || address.indexOf('BITCOIN:') === 0) { + if ( + address.indexOf("bitcoin:") === 0 || + address.indexOf("BITCOIN:") === 0 + ) { isValidBitcoinAddress = true; this.setState({ clipboardContentModalAddressType: bitcoinModalString }); } @@ -160,61 +189,74 @@ export default class App extends React.Component { isSafelloRedirect(event) { let urlObject = url.parse(event.url, true) // eslint-disable-line - return !!urlObject.query['safello-state-token']; + return !!urlObject.query["safello-state-token"]; } handleOpenURL = event => { if (event.url === null) { return; } - if (typeof event.url !== 'string') { + if (typeof event.url !== "string") { return; } if (this.isBitcoinAddress(event.url)) { this.navigator && this.navigator.dispatch( NavigationActions.navigate({ - routeName: 'SendDetails', + routeName: "SendDetails", params: { - uri: event.url, - }, - }), + uri: event.url + } + }) ); } else { - return; + return; } }; renderClipboardContentModal = () => { return ( ReactNativeHapticFeedback.trigger('impactLight', { ignoreAndroidSystemSettings: false })} + onModalShow={() => + ReactNativeHapticFeedback.trigger("impactLight", { + ignoreAndroidSystemSettings: false + }) + } isVisible={this.state.isClipboardContentModalVisible} style={styles.bottomModal} onBackdropPress={() => { this.setState({ isClipboardContentModalVisible: false }); }} > - + - You have a {this.state.clipboardContentModalAddressType} on your clipboard. Would you like to use it for a transaction? + You have a {this.state.clipboardContentModalAddressType} on your + clipboard. Would you like to use it for a transaction? this.setState({ isClipboardContentModalVisible: false })} + onPress={() => + this.setState({ isClipboardContentModalVisible: false }) + } /> { - this.setState({ isClipboardContentModalVisible: false }, async () => { - const clipboard = await Clipboard.getString(); - setTimeout(() => this.handleOpenURL({ url: clipboard }), 100); - }); + this.setState( + { isClipboardContentModalVisible: false }, + async () => { + const clipboard = await Clipboard.getString(); + setTimeout(() => this.handleOpenURL({ url: clipboard }), 100); + }); + } + ); }} /> @@ -241,24 +283,24 @@ export default class App extends React.Component { const styles = StyleSheet.create({ modalContent: { - backgroundColor: '#FFFFFF', + backgroundColor: "#FFFFFF", padding: 22, - justifyContent: 'center', - alignItems: 'center', + justifyContent: "center", + alignItems: "center", borderTopLeftRadius: 16, borderTopRightRadius: 16, - borderColor: 'rgba(0, 0, 0, 0.1)', + borderColor: "rgba(0, 0, 0, 0.1)", minHeight: 200, - height: 200, + height: 200 }, bottomModal: { - justifyContent: 'flex-end', - margin: 0, + justifyContent: "flex-end", + margin: 0 }, modelContentButtonLayout: { - flexDirection: 'row', + flexDirection: "row", margin: 16, - justifyContent: 'space-between', - alignItems: 'flex-end', - }, + justifyContent: "space-between", + alignItems: "flex-end" + } }); diff --git a/BlueApp.js b/BlueApp.js index 945fe75e4d5..c173814b76e 100644 --- a/BlueApp.js +++ b/BlueApp.js @@ -1,33 +1,40 @@ /** * @exports {AppStorage} */ -import { AppStorage } from './class'; -import DeviceQuickActions from './class/quickActions'; -let prompt = require('./prompt'); -let EV = require('./events'); -let currency = require('./currency'); -let loc = require('./loc'); +import { AppStorage } from "./class"; +import DeviceQuickActions from "./class/quickActions"; + +const prompt = require("./prompt"); +const EV = require("./events"); +const currency = require("./currency"); +const loc = require("./loc"); let BlueElectrum = require('./BlueElectrum'); // eslint-disable-line /** @type {AppStorage} */ const BlueApp = new AppStorage(); async function startAndDecrypt(retry) { - console.log('startAndDecrypt'); + console.log("startAndDecrypt"); if (BlueApp.getWallets().length > 0) { - console.log('App already has some wallets, so we are in already started state, exiting startAndDecrypt'); + console.log( + "App already has some wallets, so we are in already started state, exiting startAndDecrypt" + ); return; } let password = false; if (await BlueApp.storageIsEncrypted()) { DeviceQuickActions.clearShortcutItems(); do { - password = await prompt((retry && loc._.bad_password) || loc._.enter_password, loc._.storage_is_encrypted, false); + password = await prompt( + (retry && loc._.bad_password) || loc._.enter_password, + loc._.storage_is_encrypted, + false + ); } while (!password); } - let success = await BlueApp.loadFromDisk(password); + const success = await BlueApp.loadFromDisk(password); if (success) { - console.log('loaded from disk'); + console.log("loaded from disk"); EV(EV.enum.WALLETS_COUNT_CHANGED); EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); // now, lets try to fetch balance and txs for first wallet if it is time for it diff --git a/BlueComponents.js b/BlueComponents.js index 18e407196ab..3cf3cc1bc5b 100644 --- a/BlueComponents.js +++ b/BlueComponents.js @@ -1,1743 +1,2113 @@ /* eslint react/prop-types: 0 */ -import React, { Component, useEffect, useState } from 'react'; -import Ionicons from 'react-native-vector-icons/Ionicons'; -import PropTypes from 'prop-types'; -import { Icon, FormLabel, FormInput, Text, Header, List, ListItem } from 'react-native-elements'; +import React, { Component, useEffect, useState } from "react"; +import Ionicons from "react-native-vector-icons/Ionicons"; +import PropTypes from "prop-types"; import { - TouchableOpacity, - TouchableWithoutFeedback, - Animated, - ActivityIndicator, - View, - KeyboardAvoidingView, - UIManager, - StyleSheet, - Dimensions, - Image, - Keyboard, - SafeAreaView, - InputAccessoryView, - Clipboard, - Platform, - TextInput, -} from 'react-native'; -import LinearGradient from 'react-native-linear-gradient'; -import Carousel from 'react-native-snap-carousel'; -import { BitcoinUnit } from './models/bitcoinUnits'; -import NavigationService from './NavigationService'; -import WalletGradient from './class/walletGradient'; -import ToolTip from 'react-native-tooltip'; -import { BlurView } from '@react-native-community/blur'; -import showPopupMenu from 'react-native-popup-menu-android'; -import NetworkTransactionFees, { NetworkTransactionFeeType } from './models/networkTransactionFees'; -import Biometric from './class/biometrics'; -let loc = require('./loc/'); + Icon, + FormLabel, + FormInput, + Text, + Header, + List, + ListItem +} from "react-native-elements"; +import { + TouchableOpacity, + TouchableWithoutFeedback, + Animated, + ActivityIndicator, + View, + KeyboardAvoidingView, + UIManager, + StyleSheet, + Dimensions, + Image, + Keyboard, + SafeAreaView, + InputAccessoryView, + Clipboard, + Platform, + TextInput +} from "react-native"; +import LinearGradient from "react-native-linear-gradient"; +import Carousel from "react-native-snap-carousel"; +import { BitcoinUnit } from "./models/bitcoinUnits"; +import NavigationService from "./NavigationService"; +import WalletGradient from "./class/walletGradient"; +import ToolTip from "react-native-tooltip"; +import { BlurView } from "@react-native-community/blur"; +import showPopupMenu from "react-native-popup-menu-android"; +import NetworkTransactionFees, { + NetworkTransactionFeeType +} from "./models/networkTransactionFees"; +import Biometric from "./class/biometrics"; + +let loc = require("./loc/"); /** @type {AppStorage} */ -let BlueApp = require('./BlueApp'); -const { height, width } = Dimensions.get('window'); +let BlueApp = require("./BlueApp"); + +const { height, width } = Dimensions.get("window"); const aspectRatio = height / width; -const BigNumber = require('bignumber.js'); +const BigNumber = require("bignumber.js"); + let isIpad; if (aspectRatio > 1.6) { - isIpad = false; + isIpad = false; } else { - isIpad = true; + isIpad = true; } export class BlueButton extends Component { - render() { - let backgroundColor = this.props.backgroundColor ? this.props.backgroundColor : BlueApp.settings.buttonBackgroundColor; - let fontColor = BlueApp.settings.buttonTextColor; - if (this.props.hasOwnProperty('disabled') && this.props.disabled === true) { - backgroundColor = BlueApp.settings.buttonDisabledBackgroundColor; - fontColor = BlueApp.settings.buttonDisabledTextColor; - } - let buttonWidth = width / 1.5; - if (this.props.hasOwnProperty('noMinWidth')) { - buttonWidth = 0; + render() { + let backgroundColor = this.props.backgroundColor + ? this.props.backgroundColor + : BlueApp.settings.buttonBackgroundColor; + let fontColor = BlueApp.settings.buttonTextColor; + if (this.props.hasOwnProperty("disabled") && this.props.disabled === true) { + backgroundColor = BlueApp.settings.buttonDisabledBackgroundColor; + fontColor = BlueApp.settings.buttonDisabledTextColor; + } + let buttonWidth = width / 1.5; + if (this.props.hasOwnProperty("noMinWidth")) { + buttonWidth = 0; + } + return ( + + + {this.props.icon && ( + + )} + {this.props.title && ( + + {this.props.title} + + )} + + + ); } - return ( - - - {this.props.icon && } - {this.props.title && {this.props.title}} - - - ); - } } export class BitcoinButton extends Component { - render() { - return ( - { - // eslint-disable-next-line + render() { + return ( + { + // eslint-disable-next-line if (this.props.onPress) this.props.onPress(); - }} - > - + - - {loc.wallets.add.bitcoin} - - - - - ); - } + height: this.props.style.height, + flex: 1 + }} + > + + + {loc.wallets.add.bitcoin} + + + + + + ); + } } - - export class BlueWalletNavigationHeader extends Component { - static propTypes = { - wallet: PropTypes.shape().isRequired, - onWalletUnitChange: PropTypes.func, - }; + static propTypes = { + wallet: PropTypes.shape().isRequired, + onWalletUnitChange: PropTypes.func + }; - static getDerivedStateFromProps(props, _state) { - return { wallet: props.wallet, onWalletUnitChange: props.onWalletUnitChange }; - } + static getDerivedStateFromProps(props, _state) { + return { + wallet: props.wallet, + onWalletUnitChange: props.onWalletUnitChange + }; + } - constructor(props) { - super(props); - this.state = { wallet: props.wallet, walletPreviousPreferredUnit: props.wallet.getPreferredBalanceUnit() }; - } + constructor(props) { + super(props); + this.state = { + wallet: props.wallet, + walletPreviousPreferredUnit: props.wallet.getPreferredBalanceUnit() + }; + } - handleCopyPress = _item => { - Clipboard.setString(loc.formatBalance(this.state.wallet.getBalance(), this.state.wallet.getPreferredBalanceUnit()).toString()); - }; + handleCopyPress = _item => { + Clipboard.setString( + loc + .formatBalance( + this.state.wallet.getBalance(), + this.state.wallet.getPreferredBalanceUnit() + ) + .toString() + ); + }; - handleBalanceVisibility = async _item => { - const wallet = this.state.wallet; + handleBalanceVisibility = async _item => { + const wallet = this.state.wallet; - const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled(); + const isBiometricsEnabled = await Biometric.isBiometricUseCapableAndEnabled(); - if (isBiometricsEnabled && wallet.hideBalance) { - if (!(await Biometric.unlockWithBiometrics())) { - return this.props.navigation.goBack(); - } - } + if (isBiometricsEnabled && wallet.hideBalance) { + if (!(await Biometric.unlockWithBiometrics())) { + return this.props.navigation.goBack(); + } + } - wallet.hideBalance = !wallet.hideBalance; - this.setState({ wallet }); - await BlueApp.saveToDisk(); - }; + wallet.hideBalance = !wallet.hideBalance; + this.setState({ wallet }); + await BlueApp.saveToDisk(); + }; - showAndroidTooltip = () => { - showPopupMenu(this.toolTipMenuOptions(), this.handleToolTipSelection, this.walletBalanceText); - }; + showAndroidTooltip = () => { + showPopupMenu( + this.toolTipMenuOptions(), + this.handleToolTipSelection, + this.walletBalanceText + ); + }; - handleToolTipSelection = item => { - if (item === loc.transactions.details.copy || item.id === loc.transactions.details.copy) { - this.handleCopyPress(); - } else if (item === 'balancePrivacy' || item.id === 'balancePrivacy') { - this.handleBalanceVisibility(); - } - }; + handleToolTipSelection = item => { + if ( + item === loc.transactions.details.copy || + item.id === loc.transactions.details.copy + ) { + this.handleCopyPress(); + } else if (item === "balancePrivacy" || item.id === "balancePrivacy") { + this.handleBalanceVisibility(); + } + }; - toolTipMenuOptions() { - return Platform.select({ - // NOT WORKING ATM. - // ios: [ - // { text: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance', onPress: this.handleBalanceVisibility }, - // { text: loc.transactions.details.copy, onPress: this.handleCopyPress }, - // ], - android: this.state.wallet.hideBalance - ? [{ id: 'balancePrivacy', label: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance' }] - : [ - { id: 'balancePrivacy', label: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance' }, - { id: loc.transactions.details.copy, label: loc.transactions.details.copy }, - ], - }); - } - - changeWalletBalanceUnit() { - let walletPreviousPreferredUnit = this.state.wallet.getPreferredBalanceUnit(); - const wallet = this.state.wallet; - if (walletPreviousPreferredUnit === BitcoinUnit.BTC) { - wallet.preferredBalanceUnit = BitcoinUnit.SATS; - walletPreviousPreferredUnit = BitcoinUnit.BTC; - } else if (walletPreviousPreferredUnit === BitcoinUnit.SATS) { - wallet.preferredBalanceUnit = BitcoinUnit.BTC; - walletPreviousPreferredUnit = BitcoinUnit.SATS; - } else { - wallet.preferredBalanceUnit = BitcoinUnit.BTC; - walletPreviousPreferredUnit = BitcoinUnit.BTC; + toolTipMenuOptions() { + return Platform.select({ + // NOT WORKING ATM. + // ios: [ + // { text: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance', onPress: this.handleBalanceVisibility }, + // { text: loc.transactions.details.copy, onPress: this.handleCopyPress }, + // ], + android: this.state.wallet.hideBalance + ? [ + { + id: "balancePrivacy", + label: this.state.wallet.hideBalance + ? "Show Balance" + : "Hide Balance" + } + ] + : [ + { + id: "balancePrivacy", + label: this.state.wallet.hideBalance + ? "Show Balance" + : "Hide Balance" + }, + { + id: loc.transactions.details.copy, + label: loc.transactions.details.copy + } + ] + }); } - this.setState({ wallet, walletPreviousPreferredUnit: walletPreviousPreferredUnit }, () => { - this.props.onWalletUnitChange(wallet); - }); - } + changeWalletBalanceUnit() { + let walletPreviousPreferredUnit = this.state.wallet.getPreferredBalanceUnit(); + const wallet = this.state.wallet; + if (walletPreviousPreferredUnit === BitcoinUnit.BTC) { + wallet.preferredBalanceUnit = BitcoinUnit.SATS; + walletPreviousPreferredUnit = BitcoinUnit.BTC; + } else if (walletPreviousPreferredUnit === BitcoinUnit.SATS) { + wallet.preferredBalanceUnit = BitcoinUnit.BTC; + walletPreviousPreferredUnit = BitcoinUnit.SATS; + } else { + wallet.preferredBalanceUnit = BitcoinUnit.BTC; + walletPreviousPreferredUnit = BitcoinUnit.BTC; + } - manageFundsPressed = () => { - this.props.onManageFundsPressed(); - }; + this.setState( + { wallet, walletPreviousPreferredUnit: walletPreviousPreferredUnit }, + () => { + this.props.onWalletUnitChange(wallet); + }); + } - render() { - return ( - - { + this.props.onManageFundsPressed(); + }; + + render() { + return ( + + + + + {this.state.wallet.getLabel()} + + {Platform.OS === "ios" && ( + (this.tooltip = tooltip)} + actions={ + this.state.wallet.hideBalance + ? [ + { + text: this.state.wallet.hideBalance + ? "Show Balance" + : "Hide Balance", + onPress: this.handleBalanceVisibility + } + ] + : [ + { + text: this.state.wallet.hideBalance + ? "Show Balance" + : "Hide Balance", + onPress: this.handleBalanceVisibility + }, + { + text: loc.transactions.details.copy, + onPress: this.handleCopyPress + } + ] + } + /> + )} + this.changeWalletBalanceUnit()} + ref={ref => (this.walletBalanceText = ref)} + onLongPress={() => + Platform.OS === "ios" + ? this.tooltip.showMenu() + : this.showAndroidTooltip() } - style={{ - width: 99, - height: 94, - position: 'absolute', - bottom: 0, - right: 0, - }} - /> + > + {this.state.wallet.hideBalance ? ( + + ) : ( + + {loc + .formatBalance( + this.state.wallet.getBalance(), + this.state.wallet.getPreferredBalanceUnit(), + true + ) + .toString()} + + )} + + + ); + } +} - + - {this.state.wallet.getLabel()} - - {Platform.OS === 'ios' && ( - (this.tooltip = tooltip)} - actions={ - this.state.wallet.hideBalance - ? [{ text: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance', onPress: this.handleBalanceVisibility }] - : [ - { text: this.state.wallet.hideBalance ? 'Show Balance' : 'Hide Balance', onPress: this.handleBalanceVisibility }, - { text: loc.transactions.details.copy, onPress: this.handleCopyPress }, - ] - } - /> - )} - this.changeWalletBalanceUnit()} - ref={ref => (this.walletBalanceText = ref)} - onLongPress={() => (Platform.OS === 'ios' ? this.tooltip.showMenu() : this.showAndroidTooltip())} - > - {this.state.wallet.hideBalance ? ( - - ) : ( + {this.props.title && ( - {loc.formatBalance(this.state.wallet.getBalance(), this.state.wallet.getPreferredBalanceUnit(), true).toString()} + {this.props.title} )} - - - ); - } -} - -export class BlueButtonLink extends Component { - render() { - let backgroundColor = this.props.backgroundColor ? this.props.backgroundColor : BlueApp.settings.buttonBackgroundColor; - let fontColor = BlueApp.settings.buttonTextColor; - let buttonWidth = width / 1.5; - if (this.props.hasOwnProperty('noMinWidth')) { - buttonWidth = 0; + + + ); } - return ( - - - {this.props.title && {this.props.title}} - - - ); - } } export class BlueButtonLinkUrl extends Component { - render() { - return ( - - {this.props.title} - - ); - } + render() { + return ( + + + {this.props.title} + + + ); + } } -export const BlueNavigationStyle = (navigation, withNavigationCloseButton = false, customCloseButtonFunction = undefined) => ({ - headerStyle: { - backgroundColor: BlueApp.settings.navbarColor, - borderBottomWidth: 0, - elevation: 0, - }, - headerTitleStyle: { - fontWeight: '600', - color: BlueApp.settings.foregroundColor, - }, - headerTintColor: BlueApp.settings.foregroundColor, - headerRight: withNavigationCloseButton ? ( - { - Keyboard.dismiss(); - navigation.goBack(null); +export const BlueNavigationStyle = ( + navigation, + withNavigationCloseButton = false, + customCloseButtonFunction = undefined +) => ({ + headerStyle: { + backgroundColor: BlueApp.settings.navbarColor, + borderBottomWidth: 0, + elevation: 0 + }, + headerTitleStyle: { + fontWeight: "600", + color: BlueApp.settings.foregroundColor + }, + headerTintColor: BlueApp.settings.foregroundColor, + headerRight: withNavigationCloseButton ? ( + { + Keyboard.dismiss(); + navigation.goBack(null); + } + : customCloseButtonFunction } - : customCloseButtonFunction - } - > - - - ) : null, - headerBackTitle: null, + > + + + ) : null, + headerBackTitle: null }); -export const BlueCreateTxNavigationStyle = (navigation, withAdvancedOptionsMenuButton = false, advancedOptionsMenuButtonAction) => ({ - headerStyle: { - backgroundColor: BlueApp.settings.navbarColor, - borderBottomWidth: 0, - elevation: 0, - }, - headerTitleStyle: { - fontWeight: '600', - color: BlueApp.settings.foregroundColor, - }, - headerTintColor: BlueApp.settings.foregroundColor, - headerLeft: ( - { - Keyboard.dismiss(); - navigation.goBack(null); - }} +export const BlueCreateTxNavigationStyle = ( + navigation, + withAdvancedOptionsMenuButton = false, + advancedOptionsMenuButtonAction +) => ({ + headerStyle: { + backgroundColor: BlueApp.settings.navbarColor, + borderBottomWidth: 0, + elevation: 0 + }, + headerTitleStyle: { + fontWeight: "600", + color: BlueApp.settings.foregroundColor + }, + headerTintColor: BlueApp.settings.foregroundColor, + headerLeft: ( + { + Keyboard.dismiss(); + navigation.goBack(null); + }} + > + + + ), + headerRight: withAdvancedOptionsMenuButton ? ( + - - - ), - headerRight: withAdvancedOptionsMenuButton ? ( - - - - ) : null, - headerBackTitle: null, + + + ) : null, + headerBackTitle: null }); export const BluePrivateBalance = () => { - return Platform.select({ - ios: ( - - - - - ), - android: ( - - - - - ), - }); + return Platform.select({ + ios: ( + + + + + ), + android: ( + + + + + ) + }); }; -export const BlueCopyToClipboardButton = ({ stringToCopy, displayText = false }) => { - return ( - Clipboard.setString(stringToCopy)}> - {displayText || loc.transactions.details.copy} - - ); +export const BlueCopyToClipboardButton = ({ + stringToCopy, + displayText = false +}) => { + return ( + Clipboard.setString(stringToCopy)} + > + + {displayText || loc.transactions.details.copy} + + + ); }; export class BlueCopyTextToClipboard extends Component { - static propTypes = { - text: PropTypes.string, - }; + static propTypes = { + text: PropTypes.string + }; - static defaultProps = { - text: '', - }; + static defaultProps = { + text: "" + }; - constructor(props) { - super(props); - if (Platform.OS === 'android') { - UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true); + constructor(props) { + super(props); + if (Platform.OS === "android") { + UIManager.setLayoutAnimationEnabledExperimental && + UIManager.setLayoutAnimationEnabledExperimental(true); + } + this.state = { hasTappedText: false, address: props.text }; } - this.state = { hasTappedText: false, address: props.text }; - } - - static getDerivedStateFromProps(props, state) { - if (state.hasTappedText) { - return { hasTappedText: state.hasTappedText, address: state.address }; - } else { - return { hasTappedText: state.hasTappedText, address: props.text }; + + static getDerivedStateFromProps(props, state) { + if (state.hasTappedText) { + return { hasTappedText: state.hasTappedText, address: state.address }; + } else { + return { hasTappedText: state.hasTappedText, address: props.text }; + } } - } - - copyToClipboard = () => { - this.setState({ hasTappedText: true }, () => { - Clipboard.setString(this.props.text); - this.setState({ address: loc.wallets.xpub.copiedToClipboard }, () => { - setTimeout(() => { - this.setState({ hasTappedText: false, address: this.props.text }); - }, 1000); - }); - }); - }; - render() { - return ( - - - - {this.state.address} - - - - ); - } + copyToClipboard = () => { + this.setState({ hasTappedText: true }, () => { + Clipboard.setString(this.props.text); + this.setState({ address: loc.wallets.xpub.copiedToClipboard }, () => { + setTimeout(() => { + this.setState({ hasTappedText: false, address: this.props.text }); + }, 1000); + }); + }); + }; + + render() { + return ( + + + + {this.state.address} + + + + ); + } } const styleCopyTextToClipboard = StyleSheet.create({ - address: { - marginVertical: 32, - fontSize: 15, - color: '#9aa0aa', - textAlign: 'center', - }, + address: { + marginVertical: 32, + fontSize: 15, + color: "#9aa0aa", + textAlign: "center" + } }); export class SafeBlueArea extends Component { - render() { - return ( - - ); - } + render() { + return ( + + ); + } } export class BlueCard extends Component { - render() { - return ; - } + render() { + return ; + } } export class BlueText extends Component { - render() { - return ( - + ); + } +} +export class BlueTextCentered extends Component { + render() { + return ( + ); - } -} -export class BlueTextCentered extends Component { - render() { - return ; - } + } } export class BlueListItem extends Component { - render() { - return ( - + ); + } +} + +export class BlueFormLabel extends Component { + render() { + return ( + ); - } -} - -export class BlueFormLabel extends Component { - render() { - return ; - } + } } export class BlueFormInput extends Component { - render() { - return ( - - ); - } + containerStyle={{ + marginTop: 5, + borderColor: BlueApp.settings.inputBorderColor, + borderBottomColor: BlueApp.settings.inputBorderColor, + borderWidth: 0.5, + borderBottomWidth: 0.5, + backgroundColor: BlueApp.settings.inputBackgroundColor + }} + /> + ); + } } export class BlueFormMultiInput extends Component { - constructor(props) { - super(props); - this.state = { - selection: { start: 0, end: 0 }, - }; - } + constructor(props) { + super(props); + this.state = { + selection: { start: 0, end: 0 } + }; + } - render() { - return ( - - ); - } + render() { + return ( + + ); + } } export class BlueHeader extends Component { - render() { - return ( -
- ); - } + render() { + return ( +
+ ); + } } export class BlueHeaderDefaultSub extends Component { - render() { - return ( - -
- { - // eslint-disable-next-line + render() { + return ( + +
+ { + // eslint-disable-next-line this.props.leftText - } - - } - rightComponent={ - { - // eslint-disable-next-line + } + + } + rightComponent={ + { + // eslint-disable-next-line if (this.props.onClose) this.props.onClose(); - }} - > - - - - - - - } - {...this.props} - /> - - ); - } + }} + > + + + + + + + } + {...this.props} + /> + + ); + } } export class BlueHeaderDefaultMain extends Component { - render() { - return ( - -
- { - // eslint-disable-next-line + render() { + return ( + +
+ { + // eslint-disable-next-line this.props.leftText - } - - } - rightComponent={ - - - - } - /> - - ); - } + } + + } + rightComponent={ + + + + } + /> + + ); + } } export class BlueSpacing extends Component { - render() { - return ; - } + render() { + return ( + + ); + } } export class BlueSpacing40 extends Component { - render() { - return ; - } + render() { + return ( + + ); + } } export class BlueSpacingVariable extends Component { - render() { - if (isIpad) { - return ; - } else { - return ; + render() { + if (isIpad) { + return ; + } else { + return ; + } } - } } export class is { - static ipad() { - return isIpad; - } + static ipad() { + return isIpad; + } } export class BlueSpacing20 extends Component { - render() { - return ; - } + render() { + return ; + } } export class BlueSpacing10 extends Component { - render() { - return ; - } + render() { + return ; + } } export class BlueList extends Component { - render() { - return ( - - ); - } + render() { + return ( + + ); + } } export class BlueUseAllFundsButton extends Component { - static InputAccessoryViewID = 'useMaxInputAccessoryViewID'; - static propTypes = { - wallet: PropTypes.shape().isRequired, - onUseAllPressed: PropTypes.func.isRequired, - }; + static InputAccessoryViewID = "useMaxInputAccessoryViewID"; + static propTypes = { + wallet: PropTypes.shape().isRequired, + onUseAllPressed: PropTypes.func.isRequired + }; - render() { - const inputView = ( - - - + render() { + const inputView = ( + + + Total: - - {this.props.wallet.allowSendMax() && this.props.wallet.getBalance() > 0 ? ( - - ) : ( - + {this.props.wallet.allowSendMax() && + this.props.wallet.getBalance() > 0 ? ( + - {loc.formatBalanceWithoutSuffix(this.props.wallet.getBalance(), BitcoinUnit.BTC, true).toString()} {BitcoinUnit.BTC} - - )} - - - Keyboard.dismiss()} - /> - - - ); - if (Platform.OS === 'ios') { - return {inputView}; - } else { - return {inputView}; + title={`${loc + .formatBalanceWithoutSuffix( + this.props.wallet.getBalance(), + BitcoinUnit.BTC, + true + ) + BitcoinUnit.BTC + }`} + /> + ) : ( + + {loc + .formatBalanceWithoutSuffix( + this.props.wallet.getBalance(), + BitcoinUnit.BTC, + true + ) + .toString()}{" "} + {BitcoinUnit.BTC} + + )} + + + Keyboard.dismiss()} + /> + + + ); + if (Platform.OS === "ios") { + return ( + + {inputView} + + ); + } else { + return ( + + {inputView} + + ); + } } - } } export class BlueDismissKeyboardInputAccessory extends Component { - static InputAccessoryViewID = 'BlueDismissKeyboardInputAccessory'; + static InputAccessoryViewID = "BlueDismissKeyboardInputAccessory"; - render() { - return Platform.OS !== 'ios' ? null : ( - - - Keyboard.dismiss()} /> - - - ); - } + render() { + return Platform.OS !== "ios" ? null : ( + + + Keyboard.dismiss()} /> + + + ); + } } export class BlueDoneAndDismissKeyboardInputAccessory extends Component { - static InputAccessoryViewID = 'BlueDoneAndDismissKeyboardInputAccessory'; + static InputAccessoryViewID = "BlueDoneAndDismissKeyboardInputAccessory"; - onPasteTapped = async () => { - const clipboard = await Clipboard.getString(); - this.props.onPasteTapped(clipboard); - }; + onPasteTapped = async () => { + const clipboard = await Clipboard.getString(); + this.props.onPasteTapped(clipboard); + }; - render() { - const inputView = ( - - - - Keyboard.dismiss()} /> - - ); + render() { + const inputView = ( + + + + Keyboard.dismiss()} /> + + ); - if (Platform.OS === 'ios') { - return {inputView}; - } else { - return {inputView}; + if (Platform.OS === "ios") { + return ( + + {inputView} + + ); + } else { + return ( + + {inputView} + + ); + } } - } } export class BlueLoading extends Component { - render() { - return ( - - - - - - ); - } + render() { + return ( + + + + + + ); + } } const stylesBlueIcon = StyleSheet.create({ - container: { - flex: 1, - }, - box1: { - position: 'relative', - top: 15, - }, - box: { - alignSelf: 'flex-end', - paddingHorizontal: 14, - paddingTop: 8, - }, - boxIncoming: { - position: 'relative', - }, - ball: { - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: BlueApp.settings.buttonBackgroundColor, - }, - ballIncoming: { - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: BlueApp.settings.incomingBackgroundColor, - transform: [{ rotate: '-45deg' }], - }, - ballIncomingWithoutRotate: { - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: BlueApp.settings.incomingBackgroundColor, - }, - ballReceive: { - width: 30, - height: 30, - borderBottomLeftRadius: 15, - backgroundColor: BlueApp.settings.incomingBackgroundColor, - transform: [{ rotate: '-45deg' }], - }, - ballOutgoing: { - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: BlueApp.settings.outgoingBackgroundColor, - transform: [{ rotate: '225deg' }], - }, - ballOutgoingWithoutRotate: { - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: BlueApp.settings.outgoingBackgroundColor, - }, - ballTransparrent: { - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: 'transparent', - }, - ballDimmed: { - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: 'gray', - }, + container: { + flex: 1 + }, + box1: { + position: "relative", + top: 15 + }, + box: { + alignSelf: "flex-end", + paddingHorizontal: 14, + paddingTop: 8 + }, + boxIncoming: { + position: "relative" + }, + ball: { + width: 30, + height: 30, + borderRadius: 15, + backgroundColor: BlueApp.settings.buttonBackgroundColor + }, + ballIncoming: { + width: 30, + height: 30, + borderRadius: 15, + backgroundColor: BlueApp.settings.incomingBackgroundColor, + transform: [{ rotate: "-45deg" }] + }, + ballIncomingWithoutRotate: { + width: 30, + height: 30, + borderRadius: 15, + backgroundColor: BlueApp.settings.incomingBackgroundColor + }, + ballReceive: { + width: 30, + height: 30, + borderBottomLeftRadius: 15, + backgroundColor: BlueApp.settings.incomingBackgroundColor, + transform: [{ rotate: "-45deg" }] + }, + ballOutgoing: { + width: 30, + height: 30, + borderRadius: 15, + backgroundColor: BlueApp.settings.outgoingBackgroundColor, + transform: [{ rotate: "225deg" }] + }, + ballOutgoingWithoutRotate: { + width: 30, + height: 30, + borderRadius: 15, + backgroundColor: BlueApp.settings.outgoingBackgroundColor + }, + ballTransparrent: { + width: 30, + height: 30, + borderRadius: 15, + backgroundColor: "transparent" + }, + ballDimmed: { + width: 30, + height: 30, + borderRadius: 15, + backgroundColor: "gray" + } }); export class BluePlusIcon extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } export class BlueTransactionIncomingIcon extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } export class BlueTransactionPendingIcon extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } export class BlueTransactionExpiredIcon extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } export class BlueTransactionOnchainIcon extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } export class BlueTransactionOffchainIcon extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } export class BlueTransactionOffchainIncomingIcon extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } export class BlueTransactionOutgoingIcon extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } // export class BlueReceiveButtonIcon extends Component { - render() { - return ( - - - - - - - - {loc.receive.header} - - - - - ); - } + render() { + return ( + + + + + + + + {loc.receive.header} + + + + + ); + } } export class BlueSendButtonIcon extends Component { - render() { - return ( - - - - - - - - {loc.send.header} - - - - - ); - } + render() { + return ( + + + + + + + + {loc.send.header} + + + + + ); + } } export class ManageFundsBigButton extends Component { - render() { - return ( - - - - - - - - {loc.lnd.title} - - - - - ); - } + render() { + return ( + + + + + + + + {loc.lnd.title} + + + + + ); + } } export class BluePlusIconDimmed extends Component { - render() { - return ( - - - - - - - - ); - } + render() { + return ( + + + + + + + + ); + } } export class NewWalletPanel extends Component { - constructor(props) { - super(props); - // WalletsCarousel.handleClick = props.handleClick // because cant access `this` from _renderItem - // eslint-disable-next-line + constructor(props) { + super(props); + // WalletsCarousel.handleClick = props.handleClick // because cant access `this` from _renderItem + // eslint-disable-next-line this.handleClick = props.onPress; - } + } - render() { - return ( - { - if (this.handleClick) { - this.handleClick(); - } - }} - style={{ marginVertical: 17 }} - > - - - - {loc.wallets.list.create_a_wallet} - - - - {loc.wallets.list.create_a_wallet1} - - - {loc.wallets.list.create_a_wallet2} - - - - ); - } + render() { + return ( + { + if (this.handleClick) { + this.handleClick(); + } + }} + style={{ marginVertical: 17 }} + > + + + + {loc.wallets.list.create_a_wallet} + + + + {loc.wallets.list.create_a_wallet1} + + + {loc.wallets.list.create_a_wallet2} + + + + ); + } } -export const BlueTransactionListItem = ({ item, itemPriceUnit = BitcoinUnit.BTC }) => { - const calculateTimeLabel = () => { - const transactionTimeToReadable = loc.transactionTimeToReadable(item.received); - return setTransactionTimeToReadable(transactionTimeToReadable); - }; - const interval = setInterval(() => calculateTimeLabel(), 60000); - const [transactionTimeToReadable, setTransactionTimeToReadable] = useState('...'); - const [subtitleNumberOfLines, setSubtitleNumberOfLines] = useState(1); - - useEffect(() => { - calculateTimeLabel(); - return () => clearInterval(interval); - }, [item, itemPriceUnit]); - - const txMemo = () => { - if (BlueApp.tx_metadata[item.hash] && BlueApp.tx_metadata[item.hash]['memo']) { - return BlueApp.tx_metadata[item.hash]['memo']; - } - return item.walletLabel; - }; +export const BlueTransactionListItem = ({ + item, + itemPriceUnit = BitcoinUnit.BTC +}) => { + const calculateTimeLabel = () => { + const transactionTimeToReadable = loc.transactionTimeToReadable( + item.received + ); + return setTransactionTimeToReadable(transactionTimeToReadable); + }; + const interval = setInterval(() => calculateTimeLabel(), 60000); + const [transactionTimeToReadable, setTransactionTimeToReadable] = useState( + "..." + ); + const [subtitleNumberOfLines, setSubtitleNumberOfLines] = useState(1); - const rowTitle = () => { - if (item.type === 'user_invoice' || item.type === 'payment_request') { - if (isNaN(item.value)) { - item.value = '0'; - } - const currentDate = new Date(); - const now = (currentDate.getTime() / 1000) | 0; - const invoiceExpiration = item.timestamp + item.expire_time; - - if (invoiceExpiration > now) { - return loc.formatBalance(item.value && item.value, itemPriceUnit, true).toString(); - } else if (invoiceExpiration < now) { - if (item.ispaid) { - return loc.formatBalance(item.value && item.value, itemPriceUnit, true).toString(); + useEffect(() => { + calculateTimeLabel(); + return () => clearInterval(interval); + }, [calculateTimeLabel, interval, item, itemPriceUnit]); + + const txMemo = () => { + if ( + BlueApp.tx_metadata[item.hash] && + BlueApp.tx_metadata[item.hash]["memo"] + ) { + return BlueApp.tx_metadata[item.hash]["memo"]; + } + return item.walletLabel; + }; + + const rowTitle = () => { + if (item.type === "user_invoice" || item.type === "payment_request") { + if (isNaN(item.value)) { + item.value = "0"; + } + const currentDate = new Date(); + const now = (currentDate.getTime() / 1000) | 0; + const invoiceExpiration = item.timestamp + item.expire_time; + + if (invoiceExpiration > now) { + return loc + .formatBalance(item.value && item.value, itemPriceUnit, true) + .toString(); + } else if (invoiceExpiration < now) { + if (item.ispaid) { + return loc + .formatBalance(item.value && item.value, itemPriceUnit, true) + .toString(); + } else { + return loc.lnd.expired; + } + } } else { - return loc.lnd.expired; + return loc + .formatBalance(item.value && item.value, itemPriceUnit, true) + .toString(); } - } - } else { - return loc.formatBalance(item.value && item.value, itemPriceUnit, true).toString(); - } - }; + }; - const rowTitleStyle = () => { - let color = BlueApp.settings.successColor; + const rowTitleStyle = () => { + let color = BlueApp.settings.successColor; - if (item.type === 'user_invoice' || item.type === 'payment_request') { - const currentDate = new Date(); - const now = (currentDate.getTime() / 1000) | 0; - const invoiceExpiration = item.timestamp + item.expire_time; + if (item.type === "user_invoice" || item.type === "payment_request") { + const currentDate = new Date(); + const now = (currentDate.getTime() / 1000) | 0; + const invoiceExpiration = item.timestamp + item.expire_time; - if (invoiceExpiration > now) { - color = BlueApp.settings.successColor; - } else if (invoiceExpiration < now) { - if (item.ispaid) { - color = BlueApp.settings.successColor; - } else { - color = BlueApp.settings.failedColor; + if (invoiceExpiration > now) { + color = BlueApp.settings.successColor; + } else if (invoiceExpiration < now) { + if (item.ispaid) { + color = BlueApp.settings.successColor; + } else { + color = BlueApp.settings.failedColor; + } + } + } else if (item.value < 0) { + color = BlueApp.settings.outgoingForegroundColor; } - } - } else if (item.value < 0) { - color = BlueApp.settings.outgoingForegroundColor; - } - return { - fontWeight: '600', - fontSize: 14, - color: color, + return { + fontWeight: "600", + fontSize: 14, + color: color + }; }; - }; - const avatar = () => { + const avatar = () => { // is it lightning refill tx? - if (item.category === 'receive' && item.confirmations < 3) { - return ( - - - - ); - } - - if (item.type && item.type === 'bitcoind_tx') { - return ( - - - - ); - } - if (item.type === 'paid_invoice') { - // is it lightning offchain payment? - return ( - - - - ); - } + if (item.category === "receive" && item.confirmations < 3) { + return ( + + + + ); + } - if (item.type === 'user_invoice' || item.type === 'payment_request') { - if (!item.ispaid) { - const currentDate = new Date(); - const now = (currentDate.getTime() / 1000) | 0; - const invoiceExpiration = item.timestamp + item.expire_time; - if (invoiceExpiration < now) { - return ( - - - - ); + if (item.type && item.type === "bitcoind_tx") { + return ( + + + + ); + } + if (item.type === "paid_invoice") { + // is it lightning offchain payment? + return ( + + + + ); } - } else { - return ( - - - - ); - } - } - if (!item.confirmations) { - return ( - - - - ); - } else if (item.value < 0) { - return ( - - - - ); - } else { - return ( - - - - ); - } - }; + if (item.type === "user_invoice" || item.type === "payment_request") { + if (!item.ispaid) { + const currentDate = new Date(); + const now = (currentDate.getTime() / 1000) | 0; + const invoiceExpiration = item.timestamp + item.expire_time; + if (invoiceExpiration < now) { + return ( + + + + ); + } + } else { + return ( + + + + ); + } + } - const subtitle = () => { - return loc.transactions.list.conf + ': ' + (item.confirmations < 7 ? item.confirmations : '6')+ '/6 ' + txMemo() + (item.memo || ''); + if (!item.confirmations) { + return ( + + + + ); + } else if (item.value < 0) { + return ( + + + + ); + } else { + return ( + + + + ); + } + }; - }; + const subtitle = () => { + return ( + loc.transactions.list.conf + + ": " + + (item.confirmations < 7 ? item.confirmations : "6") + + "/6 " + + txMemo() + + (item.memo || "") + ); + }; - const onPress = () => { - if (item.hash) { - NavigationService.navigate('TransactionStatus', { hash: item.hash, walletLabel: item.walletLabel }); - } else if (item.type === 'user_invoice' || item.type === 'payment_request' || item.type === 'paid_invoice') { - const lightningWallet = BlueApp.getWallets().filter(wallet => { - if (typeof wallet === 'object') { - if (wallet.hasOwnProperty('secret')) { - return wallet.getSecret() === item.fromWallet; - } - } + const onPress = () => { + if (item.hash) { + NavigationService.navigate("TransactionStatus", { + hash: item.hash, + walletLabel: item.walletLabel }); - if (lightningWallet.length === 1) { - NavigationService.navigate('LNDViewInvoice', { - invoice: item, - fromWallet: lightningWallet[0], - isModal: false, - }); - } - } - }; + } else if ( + item.type === "user_invoice" || + item.type === "payment_request" || + item.type === "paid_invoice" + ) { + const lightningWallet = BlueApp.getWallets().filter(wallet => { + if (typeof wallet === "object") { + if (wallet.hasOwnProperty("secret")) { + return wallet.getSecret() === item.fromWallet; + } + } + }); + if (lightningWallet.length === 1) { + NavigationService.navigate("LNDViewInvoice", { + invoice: item, + fromWallet: lightningWallet[0], + isModal: false + }); + } + } + }; - const onLongPress = () => { - if (subtitleNumberOfLines === 1) { - setSubtitleNumberOfLines(0); - } - }; + const onLongPress = () => { + if (subtitleNumberOfLines === 1) { + setSubtitleNumberOfLines(0); + } + }; - return ( - - ); + return ( + + ); }; export class BlueListTransactionItem extends Component { - static propTypes = { - item: PropTypes.shape().isRequired, - itemPriceUnit: PropTypes.string, - }; + static propTypes = { + item: PropTypes.shape().isRequired, + itemPriceUnit: PropTypes.string + }; - static defaultProps = { - itemPriceUnit: BitcoinUnit.BTC, - }; + static defaultProps = { + itemPriceUnit: BitcoinUnit.BTC + }; - txMemo = () => { - if (BlueApp.tx_metadata[this.props.item.hash] && BlueApp.tx_metadata[this.props.item.hash]['memo']) { - return BlueApp.tx_metadata[this.props.item.hash]['memo']; - } - return ''; - }; + txMemo = () => { + if ( + BlueApp.tx_metadata[this.props.item.hash] && + BlueApp.tx_metadata[this.props.item.hash]["memo"] + ) { + return BlueApp.tx_metadata[this.props.item.hash]["memo"]; + } + return ""; + }; - rowTitle = () => { - const item = this.props.item; - if (item.type === 'user_invoice' || item.type === 'payment_request') { - if (isNaN(item.value)) { - item.value = '0'; - } - const currentDate = new Date(); - const now = (currentDate.getTime() / 1000) | 0; - const invoiceExpiration = item.timestamp + item.expire_time; - - if (invoiceExpiration > now) { - return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString(); - } else if (invoiceExpiration < now) { - if (item.ispaid) { - return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString(); + rowTitle = () => { + const item = this.props.item; + if (item.type === "user_invoice" || item.type === "payment_request") { + if (isNaN(item.value)) { + item.value = "0"; + } + const currentDate = new Date(); + const now = (currentDate.getTime() / 1000) | 0; + const invoiceExpiration = item.timestamp + item.expire_time; + + if (invoiceExpiration > now) { + return loc + .formatBalanceWithoutSuffix( + item.value && item.value, + this.props.itemPriceUnit, + true + ) + .toString(); + } else if (invoiceExpiration < now) { + if (item.ispaid) { + return loc + .formatBalanceWithoutSuffix( + item.value && item.value, + this.props.itemPriceUnit, + true + ) + .toString(); + } else { + return loc.lnd.expired; + } + } } else { - return loc.lnd.expired; + return loc + .formatBalanceWithoutSuffix( + item.value && item.value, + this.props.itemPriceUnit, + true + ) + .toString(); } - } - } else { - return loc.formatBalanceWithoutSuffix(item.value && item.value, this.props.itemPriceUnit, true).toString(); - } - }; + }; - rowTitleStyle = () => { - const item = this.props.item; - let color = '#37c0a1'; + rowTitleStyle = () => { + const item = this.props.item; + let color = "#37c0a1"; - if (item.type === 'user_invoice' || item.type === 'payment_request') { - const currentDate = new Date(); - const now = (currentDate.getTime() / 1000) | 0; - const invoiceExpiration = item.timestamp + item.expire_time; + if (item.type === "user_invoice" || item.type === "payment_request") { + const currentDate = new Date(); + const now = (currentDate.getTime() / 1000) | 0; + const invoiceExpiration = item.timestamp + item.expire_time; - if (invoiceExpiration > now) { - color = '#37c0a1'; - } else if (invoiceExpiration < now) { - if (item.ispaid) { - color = '#37c0a1'; - } else { - color = '#FF0000'; + if (invoiceExpiration > now) { + color = "#37c0a1"; + } else if (invoiceExpiration < now) { + if (item.ispaid) { + color = "#37c0a1"; + } else { + color = "#FF0000"; + } + } + } else if (item.value / 100000000 < 0) { + color = BlueApp.settings.foregroundColor; } - } - } else if (item.value / 100000000 < 0) { - color = BlueApp.settings.foregroundColor; - } - return { - fontWeight: '600', - fontSize: 14, - color: color, + return { + fontWeight: "600", + fontSize: 14, + color: color + }; }; - }; - avatar = () => { + avatar = () => { // is it lightning refill tx? - if (this.props.item.category === 'receive' && this.props.item.confirmations < 3) { - return ( - - - - ); - } + if ( + this.props.item.category === "receive" && + this.props.item.confirmations < 3 + ) { + return ( + + + + ); + } - if (this.props.item.type && this.props.item.type === 'bitcoind_tx') { - return ( - - - - ); - } - if (this.props.item.type === 'paid_invoice') { - // is it lightning offchain payment? - return ( - - - - ); - } + if (this.props.item.type && this.props.item.type === "bitcoind_tx") { + return ( + + + + ); + } + if (this.props.item.type === "paid_invoice") { + // is it lightning offchain payment? + return ( + + + + ); + } - if (this.props.item.type === 'user_invoice' || this.props.item.type === 'payment_request') { - if (!this.props.item.ispaid) { - const currentDate = new Date(); - const now = (currentDate.getTime() / 1000) | 0; - const invoiceExpiration = this.props.item.timestamp + this.props.item.expire_time; - if (invoiceExpiration < now) { - return ( - - - - ); + if ( + this.props.item.type === "user_invoice" || + this.props.item.type === "payment_request" + ) { + if (!this.props.item.ispaid) { + const currentDate = new Date(); + const now = (currentDate.getTime() / 1000) | 0; + const invoiceExpiration = + this.props.item.timestamp + this.props.item.expire_time; + if (invoiceExpiration < now) { + return ( + + + + ); + } + } else { + return ( + + + + ); + } } - } else { - return ( - - - - ); - } - } - if (!this.props.item.confirmations) { - return ( - - - - ); - } else if (this.props.item.value < 0) { - return ( - - - - ); - } else { - return ( - - - - ); - } - }; + if (!this.props.item.confirmations) { + return ( + + + + ); + } else if (this.props.item.value < 0) { + return ( + + + + ); + } else { + return ( + + + + ); + } + }; - subtitle = () => { - return ( - (this.props.item.confirmations < 7 ? loc.transactions.list.conf + ': ' + this.props.item.confirmations + ' ' : '') + + subtitle = () => { + return ( + (this.props.item.confirmations < 7 + ? loc.transactions.list.conf + + ": " + + this.props.item.confirmations + + " " + : "") + this.txMemo() + - (this.props.item.memo || '') - ); - }; + (this.props.item.memo || "") + ); + }; - onPress = () => { - if (this.props.item.hash) { - NavigationService.navigate('TransactionStatus', { hash: this.props.item.hash }); - } else if ( - this.props.item.type === 'user_invoice' || - this.props.item.type === 'payment_request' || - this.props.item.type === 'paid_invoice' - ) { - const lightningWallet = BlueApp.getWallets().filter(wallet => { - if (typeof wallet === 'object') { - if (wallet.hasOwnProperty('secret')) { - return wallet.getSecret() === this.props.item.fromWallet; - } - } - }); - NavigationService.navigate('LNDViewInvoice', { - invoice: this.props.item, - fromWallet: lightningWallet[0], - isModal: false, + onPress = () => { + if (this.props.item.hash) { + NavigationService.navigate("TransactionStatus", { + hash: this.props.item.hash }); - } - }; + } else if ( + this.props.item.type === "user_invoice" || + this.props.item.type === "payment_request" || + this.props.item.type === "paid_invoice" + ) { + const lightningWallet = BlueApp.getWallets().filter(wallet => { + if (typeof wallet === "object") { + if (wallet.hasOwnProperty("secret")) { + return wallet.getSecret() === this.props.item.fromWallet; + } + } + }); + NavigationService.navigate("LNDViewInvoice", { + invoice: this.props.item, + fromWallet: lightningWallet[0], + isModal: false + }); + } + }; - render() { - return ( - - ); - } + render() { + return ( + + ); + } } const sliderWidth = width * 1; @@ -1745,465 +2115,607 @@ const itemWidth = width * 0.82; const sliderHeight = 190; export class WalletsCarousel extends Component { - constructor(props) { - super(props); - // eslint-disable-next-line + constructor(props) { + super(props); + // eslint-disable-next-line WalletsCarousel.handleClick = props.handleClick; // because cant access `this` from _renderItem - WalletsCarousel.handleLongPress = props.handleLongPress; - // eslint-disable-next-line + WalletsCarousel.handleLongPress = props.handleLongPress; + // eslint-disable-next-line this.onSnapToItem = props.onSnapToItem; - } - - _renderItem({ item, index }) { - let scaleValue = new Animated.Value(1.0); - let props = { duration: 50 }; - if (Platform.OS === 'android') { - props['useNativeDriver'] = true; - } - this.onPressedIn = () => { - props.toValue = 0.9; - Animated.spring(scaleValue, props).start(); - }; - this.onPressedOut = () => { - props.toValue = 1.0; - Animated.spring(scaleValue, props).start(); - }; - - if (!item) { - return ( - { - if (WalletsCarousel.handleClick) { - WalletsCarousel.handleClick(index); - } - }} - /> - ); } - return ( - - { - if (WalletsCarousel.handleClick) { - WalletsCarousel.handleClick(index); - } - }} - > - - + _renderItem({ item, index }) { + let scaleValue = new Animated.Value(1.0); + let props = { duration: 50 }; + if (Platform.OS === "android") { + props["useNativeDriver"] = true; + } + this.onPressedIn = () => { + props.toValue = 0.9; + Animated.spring(scaleValue, props).start(); + }; + this.onPressedOut = () => { + props.toValue = 1.0; + Animated.spring(scaleValue, props).start(); + }; + + if (!item) { + return ( + { + if (WalletsCarousel.handleClick) { + WalletsCarousel.handleClick(index); + } + }} + /> + ); + } - - - {item.getLabel()} - - {item.hideBalance ? ( - - ) : ( - - {loc.formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)} - - )} - - - {loc.wallets.list.latest_transaction} - - - {loc.transactionTimeToReadable(item.getLatestTransactionTime())} - - - - - ); - } + { + if (WalletsCarousel.handleClick) { + WalletsCarousel.handleClick(index); + } + }} + > + + + + + + {item.getLabel()} + + {item.hideBalance ? ( + + ) : ( + + {loc.formatBalance( + Number(item.getBalance()), + item.getPreferredBalanceUnit(), + true + )} + + )} + + + {loc.wallets.list.latest_transaction} + + + {loc.transactionTimeToReadable(item.getLatestTransactionTime())} + + + + + ); + } - render() { - return ( - { - WalletsCarousel.carousel = c; - }} - renderItem={this._renderItem} - sliderWidth={sliderWidth} - sliderHeight={sliderHeight} - itemWidth={itemWidth} - inactiveSlideScale={1} - inactiveSlideOpacity={0.7} - contentContainerCustomStyle={{ left: -20 }} - onSnapToItem={index => { - if (this.onSnapToItem) { - this.onSnapToItem(index); - } - console.log('snapped to card #', index); - }} - /> - ); - } + render() { + return ( + { + WalletsCarousel.carousel = c; + }} + renderItem={this._renderItem} + sliderWidth={sliderWidth} + sliderHeight={sliderHeight} + itemWidth={itemWidth} + inactiveSlideScale={1} + inactiveSlideOpacity={0.7} + contentContainerCustomStyle={{ left: -20 }} + onSnapToItem={index => { + if (this.onSnapToItem) { + this.onSnapToItem(index); + } + console.log("snapped to card #", index); + }} + /> + ); + } } export class BlueAddressInput extends Component { - static propTypes = { - isLoading: PropTypes.bool, - onChangeText: PropTypes.func, - onBarScanned: PropTypes.func, - address: PropTypes.string, - placeholder: PropTypes.string, - }; + static propTypes = { + isLoading: PropTypes.bool, + onChangeText: PropTypes.func, + onBarScanned: PropTypes.func, + address: PropTypes.string, + placeholder: PropTypes.string + }; - static defaultProps = { - isLoading: false, - address: '', - placeholder: loc.wallets.details.address, - }; + static defaultProps = { + isLoading: false, + address: "", + placeholder: loc.wallets.details.address + }; - render() { - return ( - - { - this.props.onChangeText(text); - }} - placeholder={this.props.placeholder} - placeholderTextColor={BlueApp.settings.alternativeTextColor} - numberOfLines={1} - value={this.props.address} - style={{ color: BlueApp.settings.foregroundColor, flex: 1, marginHorizontal: 8, minHeight: 33 }} - editable={!this.props.isLoading} - onSubmitEditing={() => Keyboard.dismiss()} - {...this.props} - /> - { - NavigationService.navigate('ScanQrAddress', { onBarScanned: this.props.onBarScanned }); - Keyboard.dismiss(); - }} - style={{ - height: 36, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - backgroundColor: BlueApp.settings.buttonLinkUrlColor, - borderRadius: 4, - paddingVertical: 4, - paddingHorizontal: 8, - marginHorizontal: 4, + render() { + return ( + + { + this.props.onChangeText(text); + }} + placeholder={this.props.placeholder} + placeholderTextColor={BlueApp.settings.alternativeTextColor} + numberOfLines={1} + value={this.props.address} + style={{ + color: BlueApp.settings.foregroundColor, + flex: 1, + marginHorizontal: 8, + minHeight: 33 }} - > - - {loc.send.details.scan} - - - ); - } + editable={!this.props.isLoading} + onSubmitEditing={() => Keyboard.dismiss()} + {...this.props} + /> + { + NavigationService.navigate("ScanQrAddress", { + onBarScanned: this.props.onBarScanned + }); + Keyboard.dismiss(); + }} + style={{ + height: 36, + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + backgroundColor: BlueApp.settings.buttonLinkUrlColor, + borderRadius: 4, + paddingVertical: 4, + paddingHorizontal: 8, + marginHorizontal: 4 + }} + > + + + {loc.send.details.scan} + + + + ); + } } export class BlueReplaceFeeSuggestions extends Component { - static propTypes = { - onFeeSelected: PropTypes.func.isRequired, - transactionMinimum: PropTypes.number.isRequired, - }; - - static defaultProps = { - onFeeSelected: undefined, - transactionMinimum: 1, - }; + static propTypes = { + onFeeSelected: PropTypes.func.isRequired, + transactionMinimum: PropTypes.number.isRequired + }; - state = { networkFees: undefined, selectedFeeType: NetworkTransactionFeeType.FAST, customFeeValue: 0 }; + static defaultProps = { + onFeeSelected: undefined, + transactionMinimum: 1 + }; - async componentDidMount() { - const networkFees = await NetworkTransactionFees.recommendedFees(); - this.setState({ networkFees }, () => this.onFeeSelected(NetworkTransactionFeeType.FAST)); - } + state = { + networkFees: undefined, + selectedFeeType: NetworkTransactionFeeType.FAST, + customFeeValue: 0 + }; - onFeeSelected = selectedFeeType => { - if (selectedFeeType !== NetworkTransactionFeeType.CUSTOM) { - Keyboard.dismiss(); - } - if (selectedFeeType === NetworkTransactionFeeType.FAST) { - this.props.onFeeSelected(this.state.networkFees.fastestFee); - this.setState({ selectedFeeType }, () => this.props.onFeeSelected(this.state.networkFees.fastestFee)); - } else if (selectedFeeType === NetworkTransactionFeeType.MEDIUM) { - this.setState({ selectedFeeType }, () => this.props.onFeeSelected(this.state.networkFees.halfHourFee)); - } else if (selectedFeeType === NetworkTransactionFeeType.SLOW) { - this.setState({ selectedFeeType }, () => this.props.onFeeSelected(this.state.networkFees.hourFee)); - } else if (selectedFeeType === NetworkTransactionFeeType.CUSTOM) { - this.props.onFeeSelected(this.state.customFeeValue); + async componentDidMount() { + const networkFees = await NetworkTransactionFees.recommendedFees(); + this.setState({ networkFees }, () => + this.onFeeSelected(NetworkTransactionFeeType.FAST) + ); } - }; - onCustomFeeTextChange = customFee => { - this.setState({ customFeeValue: Number(customFee), selectedFeeType: NetworkTransactionFeeType.CUSTOM }, () => { - this.onFeeSelected(NetworkTransactionFeeType.CUSTOM); - }); - }; + onFeeSelected = selectedFeeType => { + if (selectedFeeType !== NetworkTransactionFeeType.CUSTOM) { + Keyboard.dismiss(); + } + if (selectedFeeType === NetworkTransactionFeeType.FAST) { + this.props.onFeeSelected(this.state.networkFees.fastestFee); + this.setState({ selectedFeeType }, () => + this.props.onFeeSelected(this.state.networkFees.fastestFee) + ); + } else if (selectedFeeType === NetworkTransactionFeeType.MEDIUM) { + this.setState({ selectedFeeType }, () => + this.props.onFeeSelected(this.state.networkFees.halfHourFee) + ); + } else if (selectedFeeType === NetworkTransactionFeeType.SLOW) { + this.setState({ selectedFeeType }, () => + this.props.onFeeSelected(this.state.networkFees.hourFee) + ); + } else if (selectedFeeType === NetworkTransactionFeeType.CUSTOM) { + this.props.onFeeSelected(this.state.customFeeValue); + } + }; - render() { - return ( - - {this.state.networkFees && ( - <> - Suggestions - this.onFeeSelected(NetworkTransactionFeeType.FAST)}> - } - : { hideChevron: true })} - /> - - this.onFeeSelected(NetworkTransactionFeeType.MEDIUM)}> - } - : { hideChevron: true })} - /> - - this.onFeeSelected(NetworkTransactionFeeType.SLOW)}> - } - : { hideChevron: true })} - /> - - - )} - this.customTextInput.focus()}> - - Custom - { + this.setState( + { + customFeeValue: Number(customFee), + selectedFeeType: NetworkTransactionFeeType.CUSTOM + }, + () => { + this.onFeeSelected(NetworkTransactionFeeType.CUSTOM); + }); + }; + + render() { + return ( + + {this.state.networkFees && ( + <> + Suggestions + this.onFeeSelected(NetworkTransactionFeeType.FAST)} + > + + ) + } + : { hideChevron: true })} + /> + + + this.onFeeSelected(NetworkTransactionFeeType.MEDIUM) + } + > + + ) + } + : { hideChevron: true })} + /> + + this.onFeeSelected(NetworkTransactionFeeType.SLOW)} + > + + ) + } + : { hideChevron: true })} + /> + + + )} + this.customTextInput.focus()}> + + - (this.customTextInput = ref)} - maxLength={9} + Custom + + + (this.customTextInput = ref)} + maxLength={9} + style={{ + borderColor: "#d2d2d2", + borderBottomColor: "#d2d2d2", + borderWidth: 1.0, + borderBottomWidth: 0.5, + borderRadius: 4, + minHeight: 33, + maxWidth: 100, + minWidth: 44, + backgroundColor: "#f5f5f5", + textAlign: "right" + }} + onFocus={() => + this.onCustomFeeTextChange(this.state.customFeeValue) + } + defaultValue={`${this.props.transactionMinimum}`} + placeholder="Custom sat/b" + inputAccessoryViewID={ + BlueDismissKeyboardInputAccessory.InputAccessoryViewID + } + /> + this.onCustomFeeTextChange(this.state.customFeeValue)} - defaultValue={`${this.props.transactionMinimum}`} - placeholder="Custom sat/b" - inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} - /> - sat/b - {this.state.selectedFeeType === NetworkTransactionFeeType.CUSTOM && } + > + sat/b + + {this.state.selectedFeeType === + NetworkTransactionFeeType.CUSTOM && ( + + )} + + + + + + The total fee rate (satoshi per byte) you want to pay should be higher + than {this.props.transactionMinimum} sat/byte + - - - - - The total fee rate (satoshi per byte) you want to pay should be higher than {this.props.transactionMinimum} sat/byte - - - ); - } + ); + } } export class BlueBitcoinAmount extends Component { - static propTypes = { - isLoading: PropTypes.bool, - amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - onChangeText: PropTypes.func, - disabled: PropTypes.bool, - unit: PropTypes.string, - }; - - static defaultProps = { - unit: BitcoinUnit.BTC, - }; + static propTypes = { + isLoading: PropTypes.bool, + amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + onChangeText: PropTypes.func, + disabled: PropTypes.bool, + unit: PropTypes.string + }; - render() { - const amount = this.props.amount || 0; - let localCurrency = loc.formatBalanceWithoutSuffix(amount, BitcoinUnit.LOCAL_CURRENCY, false); - if (this.props.unit === BitcoinUnit.BTC) { - let sat = new BigNumber(amount); - sat = sat.multipliedBy(100000000).toString(); - localCurrency = loc.formatBalanceWithoutSuffix(sat, BitcoinUnit.LOCAL_CURRENCY, false); - } else { - localCurrency = loc.formatBalanceWithoutSuffix(amount.toString(), BitcoinUnit.LOCAL_CURRENCY, false); - } - if (amount === BitcoinUnit.MAX) localCurrency = ''; // we dont want to display NaN - return ( - this.textInput.focus()}> - - - { - text = text.trim(); - text = text.replace(',', '.'); - const split = text.split('.'); - if (split.length >= 2) { - text = `${parseInt(split[0], 10)}.${split[1]}`; - } else { - text = `${parseInt(split[0], 10)}`; - } - text = this.props.unit === BitcoinUnit.BTC ? text.replace(/[^0-9.]/g, '') : text.replace(/[^0-9]/g, ''); - text = text.replace(/(\..*)\./g, '$1'); + static defaultProps = { + unit: BitcoinUnit.BTC + }; - if (text.startsWith('.')) { - text = '0.'; - } - text = text.replace(/(0{1,}.)\./g, '$1'); - if (this.props.unit !== BitcoinUnit.BTC) { - text = text.replace(/[^0-9.]/g, ''); - } - this.props.onChangeText(text); - }} - onBlur={() => { - if (this.props.onBlur) this.props.onBlur(); - }} - onFocus={() => { - if (this.props.onFocus) this.props.onFocus(); - }} - placeholder="0" - maxLength={10} - ref={textInput => (this.textInput = textInput)} - editable={!this.props.isLoading && !this.props.disabled} - value={amount} - placeholderTextColor={this.props.disabled ? BlueApp.settings.buttonDisabledTextColor : BlueApp.settings.alternativeTextColor2} - style={{ - color: this.props.disabled ? BlueApp.settings.buttonDisabledTextColor : BlueApp.settings.alternativeTextColor2, - fontSize: 36, - fontWeight: '600', - }} - /> - - {' ' + this.props.unit} - - - - + render() { + const amount = this.props.amount || 0; + let localCurrency = loc.formatBalanceWithoutSuffix( + amount, + BitcoinUnit.LOCAL_CURRENCY, + false ); - } + if (this.props.unit === BitcoinUnit.BTC) { + let sat = new BigNumber(amount); + sat = sat.multipliedBy(100000000).toString(); + localCurrency = loc.formatBalanceWithoutSuffix( + sat, + BitcoinUnit.LOCAL_CURRENCY, + false + ); + } else { + localCurrency = loc.formatBalanceWithoutSuffix( + amount.toString(), + BitcoinUnit.LOCAL_CURRENCY, + false + ); + } + if (amount === BitcoinUnit.MAX) localCurrency = ""; // we dont want to display NaN + return ( + this.textInput.focus()} + > + + + { + text = text.trim(); + text = text.replace(",", "."); + const split = text.split("."); + if (split.length >= 2) { + text = `${parseInt(split[0], 10)}.${split[1]}`; + } else { + text = `${parseInt(split[0], 10)}`; + } + text = + this.props.unit === BitcoinUnit.BTC + ? text.replace(/[^0-9.]/g, "") + : text.replace(/[^0-9]/g, ""); + text = text.replace(/(\..*)\./g, "$1"); + + if (text.startsWith(".")) { + text = "0."; + } + text = text.replace(/(0{1,}.)\./g, "$1"); + if (this.props.unit !== BitcoinUnit.BTC) { + text = text.replace(/[^0-9.]/g, ""); + } + this.props.onChangeText(text); + }} + onBlur={() => { + if (this.props.onBlur) this.props.onBlur(); + }} + onFocus={() => { + if (this.props.onFocus) this.props.onFocus(); + }} + placeholder="0" + maxLength={10} + ref={textInput => (this.textInput = textInput)} + editable={!this.props.isLoading && !this.props.disabled} + value={amount} + placeholderTextColor={ + this.props.disabled + ? BlueApp.settings.buttonDisabledTextColor + : BlueApp.settings.alternativeTextColor2 + } + style={{ + color: this.props.disabled + ? BlueApp.settings.buttonDisabledTextColor + : BlueApp.settings.alternativeTextColor2, + fontSize: 36, + fontWeight: "600" + }} + /> + + {" " + this.props.unit} + + + + + ); + } } export class NavbarLogo extends Component { - render() { - return ( - - - - - ); - } + render() { + return ( + + + + ); + } } const styles = StyleSheet.create({ - balanceBlur: { - height: 30, - width: 100, - marginRight: 16, - }, + balanceBlur: { + height: 30, + width: 100, + marginRight: 16 + } }); diff --git a/BlueElectrum.js b/BlueElectrum.js index 6b66ea4ade4..9d57bb7850e 100644 --- a/BlueElectrum.js +++ b/BlueElectrum.js @@ -1,15 +1,13 @@ -import AsyncStorage from '@react-native-community/async-storage'; +import AsyncStorage from "@react-native-community/async-storage"; //import { AppStorage } from './class/app-storage'; -const bitcoin = require('bitcoinjs-lib'); -const ElectrumClient = require('electrum-client'); -let reverse = require('buffer-reverse'); -let BigNumber = require('bignumber.js'); +const bitcoin = require("bitcoinjs-lib"); +const ElectrumClient = require("electrum-client"); +const reverse = require("buffer-reverse"); +const BigNumber = require("bignumber.js"); -const storageKey = 'ELECTRUM_PEERS'; -const defaultPeer = { host: 'electrum.veles.network', tcp: '50001' }; -const hardcodedPeers = [ - { host: 'electrum.veles.network', tcp: '50001' }, -]; +const storageKey = "ELECTRUM_PEERS"; +const defaultPeer = { host: "electrum.veles.network", tcp: "50001" }; +const hardcodedPeers = [{ host: "electrum.veles.network", tcp: "50001" }]; let mainClient = false; let mainConnected = false; @@ -17,33 +15,33 @@ let wasConnectedAtLeastOnce = false; async function connectMain() { let usingPeer = await getRandomHardcodedPeer(); - let savedPeer = null; + const savedPeer = null; if (savedPeer && savedPeer.host && savedPeer.tcp) { usingPeer = savedPeer; } try { - console.log('begin connection:', JSON.stringify(usingPeer)); - mainClient = new ElectrumClient(usingPeer.tcp, usingPeer.host, 'tcp'); + console.log("begin connection:", JSON.stringify(usingPeer)); + mainClient = new ElectrumClient(usingPeer.tcp, usingPeer.host, "tcp"); mainClient.onError = function(e) { - console.log('ElectrumClient error: ' + e); + console.log("ElectrumClient error: " + e); mainConnected = false; }; await mainClient.connect(); - const ver = await mainClient.server_version('2.7.11', '1.4'); + const ver = await mainClient.server_version("2.7.11", "1.4"); if (ver && ver[0]) { - console.log('connected to ', ver); + console.log("connected to ", ver); mainConnected = true; wasConnectedAtLeastOnce = true; // AsyncStorage.setItem(storageKey, JSON.stringify(peers)); TODO: refactor } } catch (e) { mainConnected = false; - console.log('bad connection:', JSON.stringify(usingPeer), e); + console.log("bad connection:", JSON.stringify(usingPeer), e); } if (!mainConnected) { - console.log('retry'); + console.log("retry"); mainClient.keepAlive = () => {}; // dirty hack to make it stop reconnecting mainClient.reconnect = () => {}; // dirty hack to make it stop reconnecting mainClient.close(); @@ -64,9 +62,9 @@ async function getRandomHardcodedPeer() { } //async function getSavedPeer() { - //let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST); - //let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT); - //return { host, tcp: port }; +//let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST); +//let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT); +//return { host, tcp: port }; //} /** @@ -82,12 +80,12 @@ async function getRandomDynamicPeer() { try { let peers = JSON.parse(await AsyncStorage.getItem(storageKey)); peers = peers.sort(() => Math.random() - 0.5); // shuffle - for (let peer of peers) { - let ret = {}; + for (const peer of peers) { + const ret = {}; ret.host = peer[1]; - for (let item of peer[2]) { - if (item.startsWith('t')) { - ret.tcp = item.replace('t', ''); + for (const item of peer[2]) { + if (item.startsWith("t")) { + ret.tcp = item.replace("t", ""); } } if (ret.host && ret.tcp) return ret; @@ -105,21 +103,23 @@ async function getRandomDynamicPeer() { * @returns {Promise} */ module.exports.getBalanceByAddress = async function(address) { - if (!mainClient) throw new Error('Electrum client is not connected'); - let script = bitcoin.address.toOutputScript(address); - let hash = bitcoin.crypto.sha256(script); - let reversedHash = Buffer.from(reverse(hash)); - let balance = await mainClient.blockchainScripthash_getBalance(reversedHash.toString('hex')); + if (!mainClient) throw new Error("Electrum client is not connected"); + const script = bitcoin.address.toOutputScript(address); + const hash = bitcoin.crypto.sha256(script); + const reversedHash = Buffer.from(reverse(hash)); + const balance = await mainClient.blockchainScripthash_getBalance( + reversedHash.toString("hex") + ); balance.addr = address; return balance; }; module.exports.getConfig = async function() { - if (!mainClient) throw new Error('Electrum client is not connected'); + if (!mainClient) throw new Error("Electrum client is not connected"); return { host: mainClient.host, port: mainClient.port, - status: mainClient.status, + status: mainClient.status }; }; @@ -129,11 +129,13 @@ module.exports.getConfig = async function() { * @returns {Promise} */ module.exports.getTransactionsByAddress = async function(address) { - if (!mainClient) throw new Error('Electrum client is not connected'); - let script = bitcoin.address.toOutputScript(address); - let hash = bitcoin.crypto.sha256(script); - let reversedHash = Buffer.from(reverse(hash)); - let history = await mainClient.blockchainScripthash_getHistory(reversedHash.toString('hex')); + if (!mainClient) throw new Error("Electrum client is not connected"); + const script = bitcoin.address.toOutputScript(address); + const hash = bitcoin.crypto.sha256(script); + const reversedHash = Buffer.from(reverse(hash)); + const history = await mainClient.blockchainScripthash_getHistory( + reversedHash.toString("hex") + ); return history; }; @@ -148,31 +150,39 @@ module.exports.ping = async function() { }; module.exports.multiGetTransactionsFullByAddress = async function(addresses) { - let addrTxMap = await this.multiGetHistoryByAddress(addresses) - let txList = []; - let ret = []; - for (let addr in addrTxMap) { - for (let tx of addrTxMap[addr]) { + const addrTxMap = await this.multiGetHistoryByAddress(addresses); + const txList = []; + const ret = []; + for (const addr in addrTxMap) { + for (const tx of addrTxMap[addr]) { txList.push(tx.tx_hash); } } - let txfull = await this.multiGetTransactionByTxid(txList); - for (let txid in txfull) { - let full = txfull[txid]; - for (let input of full.vin) { + const txfull = await this.multiGetTransactionByTxid(txList); + for (const txid in txfull) { + const full = txfull[txid]; + for (const input of full.vin) { if (!input.txid) continue; // now we need to fetch previous TX where this VIN became an output, so we can see its amount - let prevTxForVin = await mainClient.blockchainTransaction_get(input.txid, true); + const prevTxForVin = await mainClient.blockchainTransaction_get( + input.txid, + true + ); if (prevTxForVin && prevTxForVin.vout && prevTxForVin.vout[input.vout]) { input.value = prevTxForVin.vout[input.vout].value; // also, we extract destination address from prev output: - if (prevTxForVin.vout[input.vout].scriptPubKey && prevTxForVin.vout[input.vout].scriptPubKey.addresses) { - input.addresses = prevTxForVin.vout[input.vout].scriptPubKey.addresses; + if ( + prevTxForVin.vout[input.vout].scriptPubKey && + prevTxForVin.vout[input.vout].scriptPubKey.addresses + ) { + input.addresses = + prevTxForVin.vout[input.vout].scriptPubKey.addresses; } } } - for (let output of full.vout) { - if (output.scriptPubKey && output.scriptPubKey.addresses) output.addresses = output.scriptPubKey.addresses; + for (const output of full.vout) { + if (output.scriptPubKey && output.scriptPubKey.addresses) + output.addresses = output.scriptPubKey.addresses; } full.inputs = full.vin; full.outputs = full.vout; @@ -185,24 +195,32 @@ module.exports.multiGetTransactionsFullByAddress = async function(addresses) { }; module.exports.multiGetTransactionsFullByTxid = async function(txid_list) { - let ret = []; - let txfull = await this.multiGetTransactionByTxid(txid_list); - for (let txid in txfull) { - let full = txfull[txid]; - for (let input of full.vin) { + const ret = []; + const txfull = await this.multiGetTransactionByTxid(txid_list); + for (const txid in txfull) { + const full = txfull[txid]; + for (const input of full.vin) { if (!input.txid) continue; // now we need to fetch previous TX where this VIN became an output, so we can see its amount - let prevTxForVin = await mainClient.blockchainTransaction_get(input.txid, true); + const prevTxForVin = await mainClient.blockchainTransaction_get( + input.txid, + true + ); if (prevTxForVin && prevTxForVin.vout && prevTxForVin.vout[input.vout]) { input.value = prevTxForVin.vout[input.vout].value; // also, we extract destination address from prev output: - if (prevTxForVin.vout[input.vout].scriptPubKey && prevTxForVin.vout[input.vout].scriptPubKey.addresses) { - input.addresses = prevTxForVin.vout[input.vout].scriptPubKey.addresses; + if ( + prevTxForVin.vout[input.vout].scriptPubKey && + prevTxForVin.vout[input.vout].scriptPubKey.addresses + ) { + input.addresses = + prevTxForVin.vout[input.vout].scriptPubKey.addresses; } } } - for (let output of full.vout) { - if (output.scriptPubKey && output.scriptPubKey.addresses) output.addresses = output.scriptPubKey.addresses; + for (const output of full.vout) { + if (output.scriptPubKey && output.scriptPubKey.addresses) + output.addresses = output.scriptPubKey.addresses; } full.inputs = full.vin; full.outputs = full.vout; @@ -211,8 +229,8 @@ module.exports.multiGetTransactionsFullByTxid = async function(txid_list) { delete full.hex; ret.push(full); } - return ret -} + return ret; +}; /** * @@ -222,25 +240,27 @@ module.exports.multiGetTransactionsFullByTxid = async function(txid_list) { */ module.exports.multiGetBalanceByAddress = async function(addresses, batchsize) { batchsize = batchsize || 100; - if (!mainClient) throw new Error('Electrum client is not connected'); - let ret = { balance: 0, unconfirmed_balance: 0, addresses: {} }; - - let chunks = splitIntoChunks(addresses, batchsize); - for (let chunk of chunks) { - let scripthashes = []; - let scripthash2addr = {}; - for (let addr of chunk) { - let script = bitcoin.address.toOutputScript(addr); - let hash = bitcoin.crypto.sha256(script); + if (!mainClient) throw new Error("Electrum client is not connected"); + const ret = { balance: 0, unconfirmed_balance: 0, addresses: {} }; + + const chunks = splitIntoChunks(addresses, batchsize); + for (const chunk of chunks) { + const scripthashes = []; + const scripthash2addr = {}; + for (const addr of chunk) { + const script = bitcoin.address.toOutputScript(addr); + const hash = bitcoin.crypto.sha256(script); let reversedHash = Buffer.from(reverse(hash)); - reversedHash = reversedHash.toString('hex'); + reversedHash = reversedHash.toString("hex"); scripthashes.push(reversedHash); scripthash2addr[reversedHash] = addr; } - let balances = await mainClient.blockchainScripthash_getBalanceBatch(scripthashes); + const balances = await mainClient.blockchainScripthash_getBalanceBatch( + scripthashes + ); - for (let bal of balances) { + for (const bal of balances) { ret.balance += +bal.result.confirmed; ret.unconfirmed_balance += +bal.result.unconfirmed; ret.addresses[scripthash2addr[bal.param]] = bal.result; @@ -252,28 +272,30 @@ module.exports.multiGetBalanceByAddress = async function(addresses, batchsize) { module.exports.multiGetUtxoByAddress = async function(addresses, batchsize) { batchsize = batchsize || 100; - if (!mainClient) throw new Error('Electrum client is not connected'); - let ret = {}; - let res = [] - let uniq = {}; - let chunks = splitIntoChunks(addresses, batchsize); - for (let chunk of chunks) { - let scripthashes = []; - let scripthash2addr = {}; - for (let addr of chunk) { - let script = bitcoin.address.toOutputScript(addr); - let hash = bitcoin.crypto.sha256(script); + if (!mainClient) throw new Error("Electrum client is not connected"); + const ret = {}; + const res = []; + const uniq = {}; + const chunks = splitIntoChunks(addresses, batchsize); + for (const chunk of chunks) { + const scripthashes = []; + const scripthash2addr = {}; + for (const addr of chunk) { + const script = bitcoin.address.toOutputScript(addr); + const hash = bitcoin.crypto.sha256(script); let reversedHash = Buffer.from(reverse(hash)); - reversedHash = reversedHash.toString('hex'); + reversedHash = reversedHash.toString("hex"); scripthashes.push(reversedHash); scripthash2addr[reversedHash] = addr; } - let results = await mainClient.blockchainScripthash_listunspentBatch(scripthashes); + const results = await mainClient.blockchainScripthash_listunspentBatch( + scripthashes + ); - for (let utxos of results) { + for (const utxos of results) { ret[scripthash2addr[utxos.param]] = utxos.result; - for (let utxo of ret[scripthash2addr[utxos.param]]) { + for (const utxo of ret[scripthash2addr[utxos.param]]) { utxo.address = scripthash2addr[utxos.param]; utxo.txid = utxo.tx_hash; utxo.vout = utxo.tx_pos; @@ -287,27 +309,29 @@ module.exports.multiGetUtxoByAddress = async function(addresses, batchsize) { module.exports.multiGetHistoryByAddress = async function(addresses, batchsize) { batchsize = batchsize || 100; - if (!mainClient) throw new Error('Electrum client is not connected'); - let ret = {}; - - let chunks = splitIntoChunks(addresses, batchsize); - for (let chunk of chunks) { - let scripthashes = []; - let scripthash2addr = {}; - for (let addr of chunk) { - let script = bitcoin.address.toOutputScript(addr); - let hash = bitcoin.crypto.sha256(script); + if (!mainClient) throw new Error("Electrum client is not connected"); + const ret = {}; + + const chunks = splitIntoChunks(addresses, batchsize); + for (const chunk of chunks) { + const scripthashes = []; + const scripthash2addr = {}; + for (const addr of chunk) { + const script = bitcoin.address.toOutputScript(addr); + const hash = bitcoin.crypto.sha256(script); let reversedHash = Buffer.from(reverse(hash)); - reversedHash = reversedHash.toString('hex'); + reversedHash = reversedHash.toString("hex"); scripthashes.push(reversedHash); scripthash2addr[reversedHash] = addr; } - let results = await mainClient.blockchainScripthash_getHistoryBatch(scripthashes); + const results = await mainClient.blockchainScripthash_getHistoryBatch( + scripthashes + ); - for (let history of results) { + for (const history of results) { ret[scripthash2addr[history.param]] = history.result; - for (let hist of ret[scripthash2addr[history.param]]) { + for (const hist of ret[scripthash2addr[history.param]]) { hist.address = scripthash2addr[history.param]; } } @@ -316,16 +340,23 @@ module.exports.multiGetHistoryByAddress = async function(addresses, batchsize) { return ret; }; -module.exports.multiGetTransactionByTxid = async function(txids, batchsize, verbose) { +module.exports.multiGetTransactionByTxid = async function( + txids, + batchsize, + verbose +) { batchsize = batchsize || 100; verbose = verbose !== false; - if (!mainClient) throw new Error('Electrum client is not connected'); - let ret = {}; - - let chunks = splitIntoChunks(txids, batchsize); - for (let chunk of chunks) { - let results = await mainClient.blockchainTransaction_getBatch(chunk, verbose); - for (let txdata of results) { + if (!mainClient) throw new Error("Electrum client is not connected"); + const ret = {}; + + const chunks = splitIntoChunks(txids, batchsize); + for (const chunk of chunks) { + const results = await mainClient.blockchainTransaction_getBatch( + chunk, + verbose + ); + for (const txdata of results) { ret[txdata.param] = txdata.result; } } @@ -358,14 +389,14 @@ module.exports.waitTillConnected = async function() { if (retriesCounter++ >= 30) { clearInterval(waitTillConnectedInterval); - reject(new Error('Waiting for Electrum connection timeout')); + reject(new Error("Waiting for Electrum connection timeout")); } }, 1000); }); }; module.exports.estimateFees = async function() { - if (!mainClient) throw new Error('Electrum client is not connected'); + if (!mainClient) throw new Error("Electrum client is not connected"); let fast = await mainClient.blockchainEstimatefee(1); let medium = await mainClient.blockchainEstimatefee(5); let slow = await mainClient.blockchainEstimatefee(10); @@ -382,20 +413,22 @@ module.exports.estimateFees = async function() { * @returns {Promise} Satoshis per byte */ module.exports.estimateFee = async function(numberOfBlocks) { - if (!mainClient) throw new Error('Electrum client is not connected'); + if (!mainClient) throw new Error("Electrum client is not connected"); numberOfBlocks = numberOfBlocks || 1; - let coinUnitsPerKilobyte = await mainClient.blockchainEstimatefee(numberOfBlocks); + const coinUnitsPerKilobyte = await mainClient.blockchainEstimatefee( + numberOfBlocks + ); if (coinUnitsPerKilobyte < 1) return 1; return Math.round( new BigNumber(coinUnitsPerKilobyte) .dividedBy(1024) .multipliedBy(100000000) - .toNumber(), + .toNumber() ); }; module.exports.broadcast = async function(hex) { - if (!mainClient) throw new Error('Electrum client is not connected'); + if (!mainClient) throw new Error("Electrum client is not connected"); try { const broadcast = await mainClient.blockchainTransaction_broadcast(hex); return broadcast; @@ -405,7 +438,7 @@ module.exports.broadcast = async function(hex) { }; module.exports.broadcastV2 = async function(hex) { - if (!mainClient) throw new Error('Electrum client is not connected'); + if (!mainClient) throw new Error("Electrum client is not connected"); return mainClient.blockchainTransaction_broadcast(hex); }; @@ -416,10 +449,10 @@ module.exports.broadcastV2 = async function(hex) { * @returns {Promise} Whether provided host:port is a valid electrum server */ module.exports.testConnection = async function(host, tcpPort) { - let client = new ElectrumClient(tcpPort, host, 'tcp'); + const client = new ElectrumClient(tcpPort, host, "tcp"); try { await client.connect(); - await client.server_version('2.7.11', '1.4'); + await client.server_version("2.7.11", "1.4"); await client.server_ping(); client.keepAlive = () => {}; // dirty hack to make it stop reconnecting @@ -439,8 +472,8 @@ module.exports.forceDisconnect = () => { module.exports.hardcodedPeers = hardcodedPeers; -let splitIntoChunks = function(arr, chunkSize) { - let groups = []; +const splitIntoChunks = function(arr, chunkSize) { + const groups = []; let i; for (i = 0; i < arr.length; i += chunkSize) { groups.push(arr.slice(i, i + chunkSize)); diff --git a/MainBottomTabs.js b/MainBottomTabs.js index c070639394e..bcd8ab3896c 100644 --- a/MainBottomTabs.js +++ b/MainBottomTabs.js @@ -1,237 +1,237 @@ -import { createStackNavigator, createAppContainer } from 'react-navigation'; +import { createStackNavigator, createAppContainer } from "react-navigation"; -import SettingsContainer from './screen/settings/settings'; -import About from './screen/settings/about'; -import ReleaseNotes from './screen/settings/releasenotes'; -import Selftest from './screen/selftest'; -import Language from './screen/settings/language'; -import Currency from './screen/settings/currency'; -import EncryptStorage from './screen/settings/encryptStorage'; -import PlausibleDeniability from './screen/plausibledeniability'; -import ElectrumSettings from './screen/settings/electrumSettings'; -import DefaultView from './screen/settings/defaultView'; +import SettingsContainer from "./screen/settings/settings"; +import About from "./screen/settings/about"; +import ReleaseNotes from "./screen/settings/releasenotes"; +import Selftest from "./screen/selftest"; +import Language from "./screen/settings/language"; +import Currency from "./screen/settings/currency"; +import EncryptStorage from "./screen/settings/encryptStorage"; +import PlausibleDeniability from "./screen/plausibledeniability"; +import ElectrumSettings from "./screen/settings/electrumSettings"; +import DefaultView from "./screen/settings/defaultView"; -import WalletsList from './screen/wallets/list'; -import WalletTransactions from './screen/wallets/transactions'; -import AddWallet from './screen/wallets/add'; -import PleaseBackup from './screen/wallets/pleaseBackup'; -import ImportWallet from './screen/wallets/import'; -import WalletDetails from './screen/wallets/details'; -import WalletExport from './screen/wallets/export'; -import WalletXpub from './screen/wallets/xpub'; -import BuyBitcoin from './screen/wallets/buyBitcoin'; -import Marketplace from './screen/wallets/marketplace'; -import scanQrWif from './screen/wallets/scanQrWif'; -import ReorderWallets from './screen/wallets/reorderWallets'; -import SelectWallet from './screen/wallets/selectWallet'; +import WalletsList from "./screen/wallets/list"; +import WalletTransactions from "./screen/wallets/transactions"; +import AddWallet from "./screen/wallets/add"; +import PleaseBackup from "./screen/wallets/pleaseBackup"; +import ImportWallet from "./screen/wallets/import"; +import WalletDetails from "./screen/wallets/details"; +import WalletExport from "./screen/wallets/export"; +import WalletXpub from "./screen/wallets/xpub"; +import BuyBitcoin from "./screen/wallets/buyBitcoin"; +import Marketplace from "./screen/wallets/marketplace"; +import scanQrWif from "./screen/wallets/scanQrWif"; +import ReorderWallets from "./screen/wallets/reorderWallets"; +import SelectWallet from "./screen/wallets/selectWallet"; -import details from './screen/transactions/details'; -import TransactionStatus from './screen/transactions/transactionStatus'; -import rbf from './screen/transactions/RBF'; -import createrbf from './screen/transactions/RBF-create'; -import cpfp from './screen/transactions/CPFP'; -import rbfBumpFee from './screen/transactions/RBFBumpFee'; -import rbfCancel from './screen/transactions/RBFCancel'; +import details from "./screen/transactions/details"; +import TransactionStatus from "./screen/transactions/transactionStatus"; +import rbf from "./screen/transactions/RBF"; +import createrbf from "./screen/transactions/RBF-create"; +import cpfp from "./screen/transactions/CPFP"; +import rbfBumpFee from "./screen/transactions/RBFBumpFee"; +import rbfCancel from "./screen/transactions/RBFCancel"; -import receiveDetails from './screen/receive/details'; -import setReceiveAmount from './screen/receive/receiveAmount'; +import receiveDetails from "./screen/receive/details"; +import setReceiveAmount from "./screen/receive/receiveAmount"; -import sendDetails from './screen/send/details'; -import ScanQRCode from './screen/send/scanQrAddress'; -import sendCreate from './screen/send/create'; -import Confirm from './screen/send/confirm'; -import PsbtWithHardwareWallet from './screen/send/psbtWithHardwareWallet'; -import Success from './screen/send/success'; +import sendDetails from "./screen/send/details"; +import ScanQRCode from "./screen/send/scanQrAddress"; +import sendCreate from "./screen/send/create"; +import Confirm from "./screen/send/confirm"; +import PsbtWithHardwareWallet from "./screen/send/psbtWithHardwareWallet"; +import Success from "./screen/send/success"; const ReorderWalletsStackNavigator = createStackNavigator({ ReorderWallets: { - screen: ReorderWallets, - }, + screen: ReorderWallets + } }); const WalletsStackNavigator = createStackNavigator( { Wallets: { screen: WalletsList, - path: 'wallets', + path: "wallets" }, WalletTransactions: { screen: WalletTransactions, - path: 'WalletTransactions', - routeName: 'WalletTransactions', + path: "WalletTransactions", + routeName: "WalletTransactions" }, TransactionStatus: { - screen: TransactionStatus, + screen: TransactionStatus }, TransactionDetails: { - screen: details, + screen: details }, WalletDetails: { - screen: WalletDetails, + screen: WalletDetails }, RBF: { - screen: rbf, + screen: rbf }, CreateRBF: { - screen: createrbf, + screen: createrbf }, CPFP: { - screen: cpfp, + screen: cpfp }, RBFBumpFee: { - screen: rbfBumpFee, + screen: rbfBumpFee }, RBFCancel: { - screen: rbfCancel, + screen: rbfCancel }, Settings: { screen: SettingsContainer, - path: 'Settings', + path: "Settings", navigationOptions: { headerStyle: { - backgroundColor: '#000000', + backgroundColor: "#000000", borderBottomWidth: 0, - elevation: 0, + elevation: 0 }, - headerTintColor: '#ffffff', - }, + headerTintColor: "#ffffff" + } }, SelectWallet: { - screen: SelectWallet, + screen: SelectWallet }, Currency: { - screen: Currency, + screen: Currency }, About: { screen: About, - path: 'About', + path: "About" }, ReleaseNotes: { screen: ReleaseNotes, - path: 'ReleaseNotes', + path: "ReleaseNotes" }, Selftest: { - screen: Selftest, + screen: Selftest }, DefaultView: { screen: DefaultView, - path: 'DefaultView', + path: "DefaultView" }, Language: { screen: Language, - path: 'Language', + path: "Language" }, EncryptStorage: { screen: EncryptStorage, - path: 'EncryptStorage', + path: "EncryptStorage" }, PlausibleDeniability: { screen: PlausibleDeniability, - path: 'PlausibleDeniability', + path: "PlausibleDeniability" }, ElectrumSettings: { screen: ElectrumSettings, - path: 'ElectrumSettings', - }, + path: "ElectrumSettings" + } }, - { headerBackTitleVisible: false }, + { headerBackTitleVisible: false } ); const CreateTransactionStackNavigator = createStackNavigator({ SendDetails: { - screen: sendDetails, + screen: sendDetails }, Confirm: { - screen: Confirm, + screen: Confirm }, PsbtWithHardwareWallet: { - screen: PsbtWithHardwareWallet, + screen: PsbtWithHardwareWallet }, CreateTransaction: { screen: sendCreate, navigationOptions: { headerStyle: { - backgroundColor: '#000000', - borderBottomWidth: 0, + backgroundColor: "#000000", + borderBottomWidth: 0 }, - headerTintColor: '#ffffff', - }, + headerTintColor: "#ffffff" + } }, Success: { - screen: Success, + screen: Success }, SelectWallet: { screen: SelectWallet, navigationOptions: { - headerRight: null, - }, - }, + headerRight: null + } + } }); const CreateWalletStackNavigator = createStackNavigator({ AddWallet: { - screen: AddWallet, + screen: AddWallet }, ImportWallet: { - screen: ImportWallet, + screen: ImportWallet }, PleaseBackup: { - screen: PleaseBackup, - }, + screen: PleaseBackup + } }); const MainBottomTabs = createStackNavigator( { Wallets: { screen: WalletsStackNavigator, - path: 'wallets', + path: "wallets", navigationOptions: { - header: null, - }, + header: null + } }, AddWallet: { screen: CreateWalletStackNavigator, navigationOptions: { - header: null, - }, + header: null + } }, ScanQrWif: { - screen: scanQrWif, + screen: scanQrWif }, WalletExport: { - screen: WalletExport, + screen: WalletExport }, WalletXpub: { - screen: WalletXpub, + screen: WalletXpub }, BuyBitcoin: { - screen: BuyBitcoin, + screen: BuyBitcoin }, Marketplace: { - screen: Marketplace, + screen: Marketplace }, // SendDetails: { screen: CreateTransactionStackNavigator, navigationOptions: { - header: null, - }, + header: null + } }, SelectWallet: { screen: SelectWallet, navigationOptions: { - headerLeft: null, - }, + headerLeft: null + } }, // ReceiveDetails: { - screen: receiveDetails, + screen: receiveDetails }, ReceiveAmount: { - screen: setReceiveAmount, + screen: setReceiveAmount }, // @@ -239,19 +239,19 @@ const MainBottomTabs = createStackNavigator( // LND: ScanQrAddress: { - screen: ScanQRCode, + screen: ScanQRCode }, ReorderWallets: { screen: ReorderWalletsStackNavigator, navigationOptions: { - header: null, - }, - }, + header: null + } + } }, { - mode: 'modal', - }, + mode: "modal" + } ); export default createAppContainer(MainBottomTabs); diff --git a/MockStorage.js b/MockStorage.js index cc461bf5f06..80d9602e412 100644 --- a/MockStorage.js +++ b/MockStorage.js @@ -6,21 +6,25 @@ export default class MockStorage { setItem = jest.fn((key, value) => { return new Promise((resolve, reject) => { - return typeof key !== 'string' || typeof value !== 'string' - ? reject(new Error('key and value must be string')) + return typeof key !== "string" || typeof value !== "string" + ? reject(new Error("key and value must be string")) : resolve((this.storageCache[key] = value)); }); }); getItem = jest.fn(key => { return new Promise(resolve => { - return this.storageCache.hasOwnProperty(key) ? resolve(this.storageCache[key]) : resolve(null); + return this.storageCache.hasOwnProperty(key) + ? resolve(this.storageCache[key]) + : resolve(null); }); }); removeItem = jest.fn(key => { return new Promise((resolve, reject) => { - return this.storageCache.hasOwnProperty(key) ? resolve(delete this.storageCache[key]) : reject(new Error('No such key!')); + return this.storageCache.hasOwnProperty(key) + ? resolve(delete this.storageCache[key]) + : reject(new Error("No such key!")); }); }); @@ -29,6 +33,8 @@ export default class MockStorage { }); getAllKeys = jest.fn(key => { - return new Promise((resolve, reject) => resolve(Object.keys(this.storageCache))); + return new Promise((resolve, reject) => + resolve(Object.keys(this.storageCache)) + ); }); } diff --git a/NavigationService.js b/NavigationService.js index 9811aad5b41..728977db409 100644 --- a/NavigationService.js +++ b/NavigationService.js @@ -1,4 +1,4 @@ -import { NavigationActions } from 'react-navigation'; +import { NavigationActions } from "react-navigation"; let _navigator; @@ -10,12 +10,12 @@ function navigate(routeName, params) { _navigator.dispatch( NavigationActions.navigate({ routeName, - params, - }), + params + }) ); } export default { navigate, - setTopLevelNavigator, + setTopLevelNavigator }; diff --git a/Privacy.js b/Privacy.js index 38bce5cb818..668899262ce 100644 --- a/Privacy.js +++ b/Privacy.js @@ -1,13 +1,18 @@ -import Obscure from 'react-native-obscure'; -import { Platform } from 'react-native'; -const PrivacySnapshot = require('react-native-privacy-snapshot'); +import Obscure from "react-native-obscure"; +import { Platform } from "react-native"; + +const PrivacySnapshot = require("react-native-privacy-snapshot"); export default class Privacy { static enableBlur() { - Platform.OS === 'android' ? Obscure.activateObscure() : PrivacySnapshot.enabled(true); + Platform.OS === "android" + ? Obscure.activateObscure() + : PrivacySnapshot.enabled(true); } static disableBlur() { - Platform.OS === 'android' ? Obscure.deactivateObscure() : PrivacySnapshot.enabled(false); + Platform.OS === "android" + ? Obscure.deactivateObscure() + : PrivacySnapshot.enabled(false); } } diff --git a/UnlockWith.js b/UnlockWith.js index f4f18f9d99d..75126322435 100644 --- a/UnlockWith.js +++ b/UnlockWith.js @@ -1,98 +1,130 @@ -import React, { Component } from 'react'; -import { View, Image, TouchableOpacity } from 'react-native'; -import { Icon } from 'react-native-elements'; -import Biometric from './class/biometrics'; -import PropTypes from 'prop-types'; -import { SafeAreaView } from 'react-navigation'; +import React, { Component } from "react"; +import { View, Image, TouchableOpacity } from "react-native"; +import { Icon } from "react-native-elements"; +import Biometric from "./class/biometrics"; +import PropTypes from "prop-types"; +import { SafeAreaView } from "react-navigation"; /** @type {AppStorage} */ -const BlueApp = require('./BlueApp'); +const BlueApp = require("./BlueApp"); export default class UnlockWith extends Component { - state = { biometricType: false, isStorageEncrypted: false, isAuthenticating: false }; + state = { + biometricType: false, + isStorageEncrypted: false, + isAuthenticating: false + }; - async componentDidMount() { - let biometricType = false; - if (await Biometric.isBiometricUseCapableAndEnabled()) { - biometricType = await Biometric.biometricType(); + async componentDidMount() { + let biometricType = false; + if (await Biometric.isBiometricUseCapableAndEnabled()) { + biometricType = await Biometric.biometricType(); + } + const isStorageEncrypted = await BlueApp.storageIsEncrypted(); + this.setState({ biometricType, isStorageEncrypted }, async () => { + if (!biometricType || isStorageEncrypted) { + this.unlockWithKey(); + } else if (typeof biometricType === "string") this.unlockWithBiometrics(); + }); } - const isStorageEncrypted = await BlueApp.storageIsEncrypted(); - this.setState({ biometricType, isStorageEncrypted }, async () => { - if (!biometricType || isStorageEncrypted) { - this.unlockWithKey(); - } else if (typeof biometricType === 'string') this.unlockWithBiometrics(); - }); - } - successfullyAuthenticated = () => { - this.props.onSuccessfullyAuthenticated(); - }; + successfullyAuthenticated = () => { + this.props.onSuccessfullyAuthenticated(); + }; - unlockWithBiometrics = async () => { - if (await BlueApp.storageIsEncrypted()) { - this.unlockWithKey(); - } - this.setState({ isAuthenticating: true }, async () => { - if (await Biometric.unlockWithBiometrics()) { - await BlueApp.startAndDecrypt(); - return this.props.onSuccessfullyAuthenticated(); - } - this.setState({ isAuthenticating: false }); - }); - }; + unlockWithBiometrics = async () => { + if (await BlueApp.storageIsEncrypted()) { + this.unlockWithKey(); + } + this.setState({ isAuthenticating: true }, async () => { + if (await Biometric.unlockWithBiometrics()) { + await BlueApp.startAndDecrypt(); + return this.props.onSuccessfullyAuthenticated(); + } + this.setState({ isAuthenticating: false }); + }); + }; - unlockWithKey = () => { - this.setState({ isAuthenticating: true }, async () => { - await BlueApp.startAndDecrypt(); - this.props.onSuccessfullyAuthenticated(); - }); - }; + unlockWithKey = () => { + this.setState({ isAuthenticating: true }, async () => { + await BlueApp.startAndDecrypt(); + this.props.onSuccessfullyAuthenticated(); + }); + }; - render() { - if (!this.state.biometricType && !this.state.isStorageEncrypted) { - return ; - } - return ( - - - - - - - - {(this.state.biometricType === Biometric.TouchID || this.state.biometricType === Biometric.Biometrics) && + render() { + if (!this.state.biometricType && !this.state.isStorageEncrypted) { + return ; + } + return ( + + + + + + + + {(this.state.biometricType === Biometric.TouchID || + this.state.biometricType === Biometric.Biometrics) && + !this.state.isStorageEncrypted && ( + <> + + + + + )} + {this.state.biometricType === Biometric.FaceID && !this.state.isStorageEncrypted && ( <> - - + + - + )} - {this.state.biometricType === Biometric.FaceID && !this.state.isStorageEncrypted && ( - <> - - - - - )} - {this.state.biometricType !== false && this.state.isStorageEncrypted && ( - - )} - {this.state.isStorageEncrypted && ( - <> - - - - - )} - - - - - ); - } + {this.state.biometricType !== false && + this.state.isStorageEncrypted && ( + + )} + {this.state.isStorageEncrypted && ( + <> + + + + + )} + + + + + ); + } } UnlockWith.propTypes = { - onSuccessfullyAuthenticated: PropTypes.func, + onSuccessfullyAuthenticated: PropTypes.func }; diff --git a/WatchConnectivity.android.js b/WatchConnectivity.android.js index 837f54b8234..931c33d1d3f 100644 --- a/WatchConnectivity.android.js +++ b/WatchConnectivity.android.js @@ -6,7 +6,11 @@ export default class WatchConnectivity { getIsWatchAppInstalled() {} - async handleLightningInvoiceCreateRequest(_walletIndex, _amount, _description) {} + async handleLightningInvoiceCreateRequest( + _walletIndex, + _amount, + _description + ) {} async sendWalletsToWatch() {} } diff --git a/WatchConnectivity.ios.js b/WatchConnectivity.ios.js index 5efe3581557..d03554884c1 100644 --- a/WatchConnectivity.ios.js +++ b/WatchConnectivity.ios.js @@ -1,6 +1,8 @@ -import * as Watch from 'react-native-watch-connectivity'; -import { InteractionManager } from 'react-native'; -const loc = require('./loc'); +import * as Watch from "react-native-watch-connectivity"; +import { InteractionManager } from "react-native"; + +const loc = require("./loc"); + export default class WatchConnectivity { isAppInstalled = false; static shared = new WatchConnectivity(); @@ -17,23 +19,25 @@ export default class WatchConnectivity { WatchConnectivity.shared.isAppInstalled = isAppInstalled; Watch.subscribeToWatchState((err, watchState) => { if (!err) { - if (watchState === 'Activated') { + if (watchState === "Activated") { WatchConnectivity.shared.sendWalletsToWatch(); } } }); Watch.subscribeToMessages(async (err, message, reply) => { if (!err) { - if (message.request === 'createInvoice') { + if (message.request === "createInvoice") { const createInvoiceRequest = await this.handleLightningInvoiceCreateRequest( message.walletIndex, message.amount, - message.description, + message.description ); reply({ invoicePaymentRequest: createInvoiceRequest }); - } else if (message.message === 'sendApplicationContext') { - await WatchConnectivity.shared.sendWalletsToWatch(WatchConnectivity.shared.wallets); - } else if (message.message === 'fetchTransactions') { + } else if (message.message === "sendApplicationContext") { + await WatchConnectivity.shared.sendWalletsToWatch( + WatchConnectivity.shared.wallets + ); + } else if (message.message === "fetchTransactions") { await WatchConnectivity.shared.fetchTransactionsFunction(); } } else { @@ -57,7 +61,10 @@ export default class WatchConnectivity { } async sendWalletsToWatch(allWallets) { - if (allWallets === undefined && WatchConnectivity.shared.wallets !== undefined) { + if ( + allWallets === undefined && + WatchConnectivity.shared.wallets !== undefined + ) { allWallets = WatchConnectivity.shared.wallets; } if (allWallets && allWallets.length === 0) { @@ -66,10 +73,10 @@ export default class WatchConnectivity { return InteractionManager.runAfterInteractions(async () => { if (WatchConnectivity.shared.isAppInstalled) { - let wallets = []; + const wallets = []; for (const wallet of allWallets) { - let receiveAddress = ''; + let receiveAddress = ""; if (wallet.allowReceive()) { if (wallet.getAddressAsync) { try { @@ -83,72 +90,123 @@ export default class WatchConnectivity { receiveAddress = wallet.getAddress(); } } - let transactions = wallet.getTransactions(10); - let watchTransactions = []; + const transactions = wallet.getTransactions(10); + const watchTransactions = []; for (const transaction of transactions) { - let type = 'pendingConfirmation'; - let memo = ''; + let type = "pendingConfirmation"; + let memo = ""; let amount = 0; - if (transaction.hasOwnProperty('confirmations') && !(transaction.confirmations > 0)) { - type = 'pendingConfirmation'; - } else if (transaction.type === 'user_invoice' || transaction.type === 'payment_request') { + if ( + transaction.hasOwnProperty("confirmations") && + !(transaction.confirmations > 0) + ) { + type = "pendingConfirmation"; + } else if ( + transaction.type === "user_invoice" || + transaction.type === "payment_request" + ) { const currentDate = new Date(); const now = (currentDate.getTime() / 1000) | 0; - const invoiceExpiration = transaction.timestamp + transaction.expire_time; + const invoiceExpiration = + transaction.timestamp + transaction.expire_time; if (invoiceExpiration > now) { - type = 'pendingConfirmation'; + type = "pendingConfirmation"; } else if (invoiceExpiration < now) { if (transaction.ispaid) { - type = 'received'; + type = "received"; } else { - type = 'sent'; + type = "sent"; } } } else if (transaction.value / 100000000 < 0) { - type = 'sent'; + type = "sent"; } else { - type = 'received'; + type = "received"; } - if (transaction.type === 'user_invoice' || transaction.type === 'payment_request') { - amount = isNaN(transaction.value) ? '0' : amount; + if ( + transaction.type === "user_invoice" || + transaction.type === "payment_request" + ) { + amount = isNaN(transaction.value) ? "0" : amount; const currentDate = new Date(); const now = (currentDate.getTime() / 1000) | 0; - const invoiceExpiration = transaction.timestamp + transaction.expire_time; + const invoiceExpiration = + transaction.timestamp + transaction.expire_time; if (invoiceExpiration > now) { - amount = loc.formatBalance(transaction.value, wallet.getPreferredBalanceUnit(), true).toString(); + amount = loc + .formatBalance( + transaction.value, + wallet.getPreferredBalanceUnit(), + true + ) + .toString(); } else if (invoiceExpiration < now) { if (transaction.ispaid) { - amount = loc.formatBalance(transaction.value, wallet.getPreferredBalanceUnit(), true).toString(); + amount = loc + .formatBalance( + transaction.value, + wallet.getPreferredBalanceUnit(), + true + ) + .toString(); } else { amount = loc.lnd.expired; } } else { - amount = loc.formatBalance(transaction.value, wallet.getPreferredBalanceUnit(), true).toString(); + amount = loc + .formatBalance( + transaction.value, + wallet.getPreferredBalanceUnit(), + true + ) + .toString(); } } else { - amount = loc.formatBalance(transaction.value, wallet.getPreferredBalanceUnit(), true).toString(); + amount = loc + .formatBalance( + transaction.value, + wallet.getPreferredBalanceUnit(), + true + ) + .toString(); } - if (WatchConnectivity.shared.tx_metadata[transaction.hash] && WatchConnectivity.shared.tx_metadata[transaction.hash]['memo']) { - memo = WatchConnectivity.shared.tx_metadata[transaction.hash]['memo']; + if ( + WatchConnectivity.shared.tx_metadata[transaction.hash] && + WatchConnectivity.shared.tx_metadata[transaction.hash]["memo"] + ) { + memo = + WatchConnectivity.shared.tx_metadata[transaction.hash]["memo"]; } else if (transaction.memo) { memo = transaction.memo; } - const watchTX = { type, amount, memo, time: loc.transactionTimeToReadable(transaction.received) }; + const watchTX = { + type, + amount, + memo, + time: loc.transactionTimeToReadable(transaction.received) + }; watchTransactions.push(watchTX); } wallets.push({ label: wallet.getLabel(), - balance: loc.formatBalance(Number(wallet.getBalance()), wallet.getPreferredBalanceUnit(), true), + balance: loc.formatBalance( + Number(wallet.getBalance()), + wallet.getPreferredBalanceUnit(), + true + ), type: wallet.type, preferredBalanceUnit: wallet.getPreferredBalanceUnit(), receiveAddress: receiveAddress, - transactions: watchTransactions, + transactions: watchTransactions }); } - Watch.updateApplicationContext({ wallets, randomID: Math.floor(Math.random() * 11) }); + Watch.updateApplicationContext({ + wallets, + randomID: Math.floor(Math.random() * 11) + }); return { wallets }; } }); diff --git a/analytics.js b/analytics.js index 792d70142dc..127e2fce314 100644 --- a/analytics.js +++ b/analytics.js @@ -1,15 +1,15 @@ -import amplitude from 'amplitude-js'; -import Analytics from 'appcenter-analytics'; -import { getVersion } from 'react-native-device-info'; -import { Platform } from 'react-native'; +import amplitude from "amplitude-js"; +import Analytics from "appcenter-analytics"; +import { getVersion } from "react-native-device-info"; +import { Platform } from "react-native"; -amplitude.getInstance().init('8b7cf19e8eea3cdcf16340f5fbf16330', null, { +amplitude.getInstance().init("8b7cf19e8eea3cdcf16340f5fbf16330", null, { useNativeDeviceInfo: true, - platform: Platform.OS, + platform: Platform.OS }); amplitude.getInstance().setVersionName(getVersion()); -let A = async event => { +const A = async event => { amplitude.getInstance().logEvent(event, {}); try { Analytics.trackEvent(event); @@ -19,12 +19,12 @@ let A = async event => { }; A.ENUM = { - INIT: 'INIT', - GOT_NONZERO_BALANCE: 'GOT_NONZERO_BALANCE', - GOT_ZERO_BALANCE: 'GOT_ZERO_BALANCE', - CREATED_WALLET: 'CREATED_WALLET', - CREATED_LIGHTNING_WALLET: 'CREATED_LIGHTNING_WALLET', - APP_UNSUSPENDED: 'APP_UNSUSPENDED', + INIT: "INIT", + GOT_NONZERO_BALANCE: "GOT_NONZERO_BALANCE", + GOT_ZERO_BALANCE: "GOT_ZERO_BALANCE", + CREATED_WALLET: "CREATED_WALLET", + CREATED_LIGHTNING_WALLET: "CREATED_LIGHTNING_WALLET", + APP_UNSUSPENDED: "APP_UNSUSPENDED" }; module.exports = A; diff --git a/appcenter-post-build-get-pr-number.js b/appcenter-post-build-get-pr-number.js index 8e87b553284..ee3355e0343 100755 --- a/appcenter-post-build-get-pr-number.js +++ b/appcenter-post-build-get-pr-number.js @@ -1,44 +1,46 @@ -const https = require('https'); +const https = require("https"); -const auth = 'Basic ' + Buffer.from(process.env.GITHUB).toString('base64'); +const auth = "Basic " + Buffer.from(process.env.GITHUB).toString("base64"); -const branch = require('child_process') - .execSync('git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3') +const branch = require("child_process") + .execSync( + "git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3" + ) .toString() .trim(); const req = https.request( { - hostname: 'api.github.com', + hostname: "api.github.com", port: 443, - path: '/repos/BlueWallet/BlueWallet/pulls', - method: 'GET', - headers: { 'User-Agent': 'BlueWallet bot', Authorization: auth }, + path: "/repos/BlueWallet/BlueWallet/pulls", + method: "GET", + headers: { "User-Agent": "BlueWallet bot", Authorization: auth } }, resp => { - let data = ''; + let data = ""; - resp.on('data', chunk => { + resp.on("data", chunk => { data += chunk; }); - resp.on('end', () => { + resp.on("end", () => { try { const prs = JSON.parse(data); - for (let pr of prs) { + for (const pr of prs) { if (branch === pr.head.ref) { console.log(pr.number); } } } catch (err) { console.log(err); - console.log('got json: ', data); + console.log("got json: ", data); } }); - }, + } ); -req.on('error', e => { +req.on("error", e => { console.error(e); }); diff --git a/babel.config.js b/babel.config.js index f842b77fcfb..b62027c4ac5 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,3 @@ module.exports = { - presets: ['module:metro-react-native-babel-preset'], + presets: ["module:metro-react-native-babel-preset"] }; diff --git a/class/abstract-hd-wallet.js b/class/abstract-hd-wallet.js index 56cdf8c3775..fdb9f13a4aa 100644 --- a/class/abstract-hd-wallet.js +++ b/class/abstract-hd-wallet.js @@ -1,14 +1,15 @@ -import { LegacyWallet } from './legacy-wallet'; -const bip39 = require('bip39'); -const BlueElectrum = require('../BlueElectrum'); +import { LegacyWallet } from "./legacy-wallet"; + +const bip39 = require("bip39"); +const BlueElectrum = require("../BlueElectrum"); export class AbstractHDWallet extends LegacyWallet { - static type = 'abstract'; - static typeReadable = 'abstract'; + static type = "abstract"; + static typeReadable = "abstract"; constructor() { super(); - this._xpub = ''; // cache + this._xpub = ""; // cache this._address = []; this._address_to_wif_cache = {}; this._addr_balances = {}; @@ -22,7 +23,7 @@ export class AbstractHDWallet extends LegacyWallet { } generate() { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } allowSend() { @@ -35,7 +36,9 @@ export class AbstractHDWallet extends LegacyWallet { setSecret(newSecret) { this.secret = newSecret.trim().toLowerCase(); - this.secret = this.secret.replace(/[^a-zA-Z0-9]/g, ' ').replace(/\s+/g, ' '); + this.secret = this.secret + .replace(/[^a-zA-Z0-9]/g, " ") + .replace(/\s+/g, " "); this.generateAddresses(); return this; } @@ -58,8 +61,8 @@ export class AbstractHDWallet extends LegacyWallet { _getAddressWithLowestBalance() { let min = 1e6; let addr_min = false; - for (let addr in this._addr_balances) { - let balance = this._addr_balances[addr].total; + for (const addr in this._addr_balances) { + const balance = this._addr_balances[addr].total; if (balance === 0) return addr; if (balance < min) { min = balance; @@ -70,40 +73,42 @@ export class AbstractHDWallet extends LegacyWallet { } _getExternalWIFByIndex(index) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } _getInternalWIFByIndex(index) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } _getExternalAddressByIndex(index) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } _getInternalAddressByIndex(index) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } getXpub() { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } async fetchTransactions() { - let txids_to_update = [] + const txids_to_update = []; try { this._lastTxFetch = +new Date(); - let tx_addr_dict = await BlueElectrum.multiGetHistoryByAddress(this.getAddress()); - for (let addr in tx_addr_dict) { - for (let tx of tx_addr_dict[addr]) { - if (!this.transactionConfirmed(tx.tx_hash)) txids_to_update.push(tx.tx_hash); + const tx_addr_dict = await BlueElectrum.multiGetHistoryByAddress( + this.getAddress() + ); + for (const addr in tx_addr_dict) { + for (const tx of tx_addr_dict[addr]) { + if (!this.transactionConfirmed(tx.tx_hash)) + txids_to_update.push(tx.tx_hash); } } - if (txids_to_update) await this._update_unconfirmed_tx(txids_to_update); + if (txids_to_update) await this._update_unconfirmed_tx(txids_to_update); } catch (err) { console.warn(err.message); } - } getAddress() { @@ -117,27 +122,32 @@ export class AbstractHDWallet extends LegacyWallet { * @return {String} WIF if found */ _getWifForAddress(address) { - if (this._address_to_wif_cache[address]) return this._address_to_wif_cache[address]; - throw new Error('Could not find WIF for ' + address); + if (this._address_to_wif_cache[address]) + return this._address_to_wif_cache[address]; + throw new Error("Could not find WIF for " + address); } createTx() { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } async fetchBalance() { - try { - let balance = await BlueElectrum.multiGetBalanceByAddress(this.getAddress()); - this.balance = balance.balance + balance.unconfirmed_balance; - this.unconfirmed_balance = balance.unconfirmed_balance; - this._lastBalanceFetch = +new Date(); - for (let address in balance.addresses) { - this._addr_balances[address] = { - total: balance.addresses[address].unconfirmed + balance.addresses[address].confirmed, - c: balance.addresses[address].confirmed, - u: balance.addresses[address].unconfirmed, - }; - } + try { + const balance = await BlueElectrum.multiGetBalanceByAddress( + this.getAddress() + ); + this.balance = balance.balance + balance.unconfirmed_balance; + this.unconfirmed_balance = balance.unconfirmed_balance; + this._lastBalanceFetch = +new Date(); + for (const address in balance.addresses) { + this._addr_balances[address] = { + total: + balance.addresses[address].unconfirmed + + balance.addresses[address].confirmed, + c: balance.addresses[address].confirmed, + u: balance.addresses[address].unconfirmed + }; + } } catch (err) { console.warn(err.message); } @@ -146,7 +156,7 @@ export class AbstractHDWallet extends LegacyWallet { async fetchUtxo() { try { this.utxo = []; - let utxos = await BlueElectrum.multiGetUtxoByAddress(this.getAddress()); + const utxos = await BlueElectrum.multiGetUtxoByAddress(this.getAddress()); this.utxo = utxos; } catch (err) { console.warn(err.message); @@ -158,14 +168,14 @@ export class AbstractHDWallet extends LegacyWallet { } _getDerivationPathByAddress(address) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } _getNodePubkeyByIndex(address) { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } generateAddresses() { - throw new Error('Not implemented'); + throw new Error("Not implemented"); } } diff --git a/class/abstract-wallet.js b/class/abstract-wallet.js index fa08871f4e8..c2c4470b4d5 100644 --- a/class/abstract-wallet.js +++ b/class/abstract-wallet.js @@ -1,13 +1,15 @@ -import { BitcoinUnit, Chain } from '../models/bitcoinUnits'; -const createHash = require('create-hash'); +import { BitcoinUnit, Chain } from "../models/bitcoinUnits"; + +const createHash = require("create-hash"); + export class AbstractWallet { - static type = 'abstract'; - static typeReadable = 'abstract'; + static type = "abstract"; + static typeReadable = "abstract"; static fromJson(obj) { - let obj2 = JSON.parse(obj); - let temp = new this(); - for (let key2 of Object.keys(obj2)) { + const obj2 = JSON.parse(obj); + const temp = new this(); + for (const key2 of Object.keys(obj2)) { temp[key2] = obj2[key2]; } @@ -17,8 +19,8 @@ export class AbstractWallet { constructor() { this.type = this.constructor.type; this.typeReadable = this.constructor.typeReadable; - this.label = ''; - this.secret = ''; // private key or recovery phrase + this.label = ""; + this.secret = ""; // private key or recovery phrase this.balance = 0; // SAT this.unconfirmed_balance = 0; // SAT this.transactions = []; @@ -33,10 +35,10 @@ export class AbstractWallet { } getID() { - return createHash('sha256') + return createHash("sha256") .update(this.getSecret()) .digest() - .toString('hex'); + .toString("hex"); } getTransactions() { @@ -64,7 +66,7 @@ export class AbstractWallet { } getPreferredBalanceUnit() { - for (let value of Object.values(BitcoinUnit)) { + for (const value of Object.values(BitcoinUnit)) { if (value === this.preferredBalanceUnit) { return this.preferredBalanceUnit; } @@ -127,7 +129,7 @@ export class AbstractWallet { // createTx () { throw Error('not implemented') } getAddress() { - throw Error('not implemented'); + throw Error("not implemented"); } getAddressAsync() { diff --git a/class/app-storage.js b/class/app-storage.js index a8765fbd1e7..a754bf6f576 100644 --- a/class/app-storage.js +++ b/class/app-storage.js @@ -1,5 +1,5 @@ -import AsyncStorage from '@react-native-community/async-storage'; -import RNSecureKeyStore, { ACCESSIBLE } from 'react-native-secure-key-store'; +import AsyncStorage from "@react-native-community/async-storage"; +import RNSecureKeyStore, { ACCESSIBLE } from "react-native-secure-key-store"; import { HDSegwitP2SHWallet, HDLegacyP2PKHWallet, @@ -7,21 +7,22 @@ import { LegacyWallet, SegwitP2SHWallet, SegwitBech32Wallet, - HDSegwitBech32Wallet, -} from './'; -import WatchConnectivity from '../WatchConnectivity'; -import DeviceQuickActions from './quickActions'; -const encryption = require('../encryption'); + HDSegwitBech32Wallet +} from "./"; +import WatchConnectivity from "../WatchConnectivity"; +import DeviceQuickActions from "./quickActions"; + +const encryption = require("../encryption"); export class AppStorage { - static FLAG_ENCRYPTED = 'data_encrypted'; - static LANG = 'lang'; - static EXCHANGE_RATES = 'currency'; - static LNDHUB = 'lndhub'; - static ELECTRUM_HOST = 'electrum_host'; - static ELECTRUM_TCP_PORT = 'electrum_tcp_port'; - static PREFERRED_CURRENCY = 'preferredCurrency'; - static ADVANCED_MODE_ENABLED = 'advancedmodeenabled'; + static FLAG_ENCRYPTED = "data_encrypted"; + static LANG = "lang"; + static EXCHANGE_RATES = "currency"; + static LNDHUB = "lndhub"; + static ELECTRUM_HOST = "electrum_host"; + static ELECTRUM_TCP_PORT = "electrum_tcp_port"; + static PREFERRED_CURRENCY = "preferredCurrency"; + static ADVANCED_MODE_ENABLED = "advancedmodeenabled"; constructor() { /** {Array.} */ @@ -29,32 +30,32 @@ export class AppStorage { this.tx_metadata = {}; this.cachedPassword = false; this.settings = { - brandingColor: '#383737', - foregroundColor: '#ffffff', - buttonBackgroundColor: 'rgba(38, 38, 38, 0.9)', - buttonTextColor: '#ffffff', - buttonAlternativeTextColor: '#ffffff', - buttonDisabledBackgroundColor: 'rgba(38, 38, 38, 0.9)', - buttonDisabledTextColor: '#9aa0aa', - buttonLinkUrlColor: '#e4b99c', - inputBorderColor: 'rgba(38, 38, 38, 0.9)', - inputBackgroundColor: 'rgba(38, 38, 38, 0.9)', - alternativeTextColor: '#9aa0aa', - alternativeTextColor2: '#f19b7e', - buttonBlueBackgroundColor: 'rgba(38, 38, 38, 0.9)', - incomingBackgroundColor: 'rgba(38, 38, 38, 1)', - incomingForegroundColor: '#aeed6a', - outgoingBackgroundColor: 'rgba(38, 38, 38, 1)', - outgoingForegroundColor: '#FAA', - successColor: '#aeed6a', - failedColor: '#FAA', - shadowColor: '#000000', - inverseForegroundColor: '#ffffff', - hdborderColor: '#68BBE1', - hdbackgroundColor: '#ECF9FF', - navbarColor: '#000000', - lnborderColor: '#F7C056', - lnbackgroundColor: '#FFFAEF', + brandingColor: "#383737", + foregroundColor: "#ffffff", + buttonBackgroundColor: "rgba(38, 38, 38, 0.9)", + buttonTextColor: "#ffffff", + buttonAlternativeTextColor: "#ffffff", + buttonDisabledBackgroundColor: "rgba(38, 38, 38, 0.9)", + buttonDisabledTextColor: "#9aa0aa", + buttonLinkUrlColor: "#e4b99c", + inputBorderColor: "rgba(38, 38, 38, 0.9)", + inputBackgroundColor: "rgba(38, 38, 38, 0.9)", + alternativeTextColor: "#9aa0aa", + alternativeTextColor2: "#f19b7e", + buttonBlueBackgroundColor: "rgba(38, 38, 38, 0.9)", + incomingBackgroundColor: "rgba(38, 38, 38, 1)", + incomingForegroundColor: "#aeed6a", + outgoingBackgroundColor: "rgba(38, 38, 38, 1)", + outgoingForegroundColor: "#FAA", + successColor: "#aeed6a", + failedColor: "#FAA", + shadowColor: "#000000", + inverseForegroundColor: "#ffffff", + hdborderColor: "#68BBE1", + hdbackgroundColor: "#ECF9FF", + navbarColor: "#000000", + lnborderColor: "#F7C056", + lnbackgroundColor: "#FFFAEF" }; } @@ -67,8 +68,13 @@ export class AppStorage { * @returns {Promise|Promise | Promise | * | Promise | void} */ setItem(key, value) { - if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { - return RNSecureKeyStore.set(key, value, { accessible: ACCESSIBLE.WHEN_UNLOCKED }); + if ( + typeof navigator !== "undefined" && + navigator.product === "ReactNative" + ) { + return RNSecureKeyStore.set(key, value, { + accessible: ACCESSIBLE.WHEN_UNLOCKED + }); } else { return AsyncStorage.setItem(key, value); } @@ -82,7 +88,10 @@ export class AppStorage { * @returns {Promise|*} */ getItem(key) { - if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { + if ( + typeof navigator !== "undefined" && + navigator.product === "ReactNative" + ) { return RNSecureKeyStore.get(key); } else { return AsyncStorage.getItem(key); @@ -110,7 +119,7 @@ export class AppStorage { decryptData(data, password) { data = JSON.parse(data); let decrypted; - for (let value of data) { + for (const value of data) { try { decrypted = encryption.decrypt(value, password); } catch (e) { @@ -128,16 +137,16 @@ export class AppStorage { async encryptStorage(password) { // assuming the storage is not yet encrypted await this.saveToDisk(); - let data = await this.getItem('data'); + let data = await this.getItem("data"); // TODO: refactor ^^^ (should not save & load to fetch data) - let encrypted = encryption.encrypt(data, password); + const encrypted = encryption.encrypt(data, password); data = []; data.push(encrypted); // putting in array as we might have many buckets with storages data = JSON.stringify(data); this.cachedPassword = password; - await this.setItem('data', data); - await this.setItem(AppStorage.FLAG_ENCRYPTED, '1'); + await this.setItem("data", data); + await this.setItem(AppStorage.FLAG_ENCRYPTED, "1"); DeviceQuickActions.clearShortcutItems(); DeviceQuickActions.removeAllWallets(); } @@ -152,18 +161,18 @@ export class AppStorage { this.wallets = []; this.tx_metadata = {}; - let data = { + const data = { wallets: [], - tx_metadata: {}, + tx_metadata: {} }; - let buckets = await this.getItem('data'); + let buckets = await this.getItem("data"); buckets = JSON.parse(buckets); buckets.push(encryption.encrypt(JSON.stringify(data), fakePassword)); this.cachedPassword = fakePassword; const bucketsString = JSON.stringify(buckets); - await this.setItem('data', bucketsString); - return (await this.getItem('data')) === bucketsString; + await this.setItem("data", bucketsString); + return (await this.getItem("data")) === bucketsString; } /** @@ -175,7 +184,7 @@ export class AppStorage { */ async loadFromDisk(password) { try { - let data = await this.getItem('data'); + let data = await this.getItem("data"); if (password) { data = this.decryptData(data, password); if (data) { @@ -186,10 +195,10 @@ export class AppStorage { if (data !== null) { data = JSON.parse(data); if (!data.wallets) return false; - let wallets = data.wallets; - for (let key of wallets) { + const wallets = data.wallets; + for (const key of wallets) { // deciding which type is wallet and instatiating correct object - let tempObj = JSON.parse(key); + const tempObj = JSON.parse(key); let unserializedWallet; switch (tempObj.type) { case SegwitBech32Wallet.type: @@ -217,7 +226,11 @@ export class AppStorage { break; } // done - if (!this.wallets.some(wallet => wallet.getSecret() === unserializedWallet.secret)) { + if ( + !this.wallets.some( + wallet => wallet.getSecret() === unserializedWallet.secret + ) + ) { this.wallets.push(unserializedWallet); this.tx_metadata = data.tx_metadata; } @@ -248,10 +261,10 @@ export class AppStorage { * @param wallet {AbstractWallet} */ deleteWallet(wallet) { - let secret = wallet.getSecret(); - let tempWallets = []; + const secret = wallet.getSecret(); + const tempWallets = []; - for (let value of this.wallets) { + for (const value of this.wallets) { if (value.getSecret() === secret) { // the one we should delete // nop @@ -271,45 +284,47 @@ export class AppStorage { * @returns {Promise} Result of storage save */ async saveToDisk() { - let walletsToSave = []; - for (let key of this.wallets) { - if (typeof key === 'boolean') continue; + const walletsToSave = []; + for (const key of this.wallets) { + if (typeof key === "boolean") continue; if (key.prepareForSerialization) key.prepareForSerialization(); walletsToSave.push(JSON.stringify({ ...key, type: key.type })); } let data = { wallets: walletsToSave, - tx_metadata: this.tx_metadata, + tx_metadata: this.tx_metadata }; if (this.cachedPassword) { // should find the correct bucket, encrypt and then save - let buckets = await this.getItem('data'); + let buckets = await this.getItem("data"); buckets = JSON.parse(buckets); - let newData = []; - for (let bucket of buckets) { - let decrypted = encryption.decrypt(bucket, this.cachedPassword); + const newData = []; + for (const bucket of buckets) { + const decrypted = encryption.decrypt(bucket, this.cachedPassword); if (!decrypted) { // no luck decrypting, its not our bucket newData.push(bucket); } else { // decrypted ok, this is our bucket // we serialize our object's data, encrypt it, and add it to buckets - newData.push(encryption.encrypt(JSON.stringify(data), this.cachedPassword)); - await this.setItem(AppStorage.FLAG_ENCRYPTED, '1'); + newData.push( + encryption.encrypt(JSON.stringify(data), this.cachedPassword) + ); + await this.setItem(AppStorage.FLAG_ENCRYPTED, "1"); } } data = newData; } else { - await this.setItem(AppStorage.FLAG_ENCRYPTED, ''); // drop the flag + await this.setItem(AppStorage.FLAG_ENCRYPTED, ""); // drop the flag } WatchConnectivity.shared.wallets = this.wallets; WatchConnectivity.shared.tx_metadata = this.tx_metadata; WatchConnectivity.shared.sendWalletsToWatch(); DeviceQuickActions.setWallets(this.wallets); DeviceQuickActions.setQuickActions(); - return this.setItem('data', JSON.stringify(data)); + return this.setItem("data", JSON.stringify(data)); } /** @@ -321,16 +336,16 @@ export class AppStorage { * @return {Promise.} */ async fetchWalletBalances(index) { - console.log('fetchWalletBalances for wallet#', index); + console.log("fetchWalletBalances for wallet#", index); if (index || index === 0) { let c = 0; - for (let wallet of this.wallets) { + for (const wallet of this.wallets) { if (c++ === index) { await wallet.fetchBalance(); } } } else { - for (let wallet of this.wallets) { + for (const wallet of this.wallets) { await wallet.fetchBalance(); } } @@ -344,13 +359,13 @@ export class AppStorage { * * @param index {Integer} Index of the wallet in this.wallets array, * blank to fetch from all wallets - * @return {Promise.} + * @return {Promise.} */ async fetchWalletTransactions(index) { - console.log('fetchWalletTransactions for wallet#', index); + console.log("fetchWalletTransactions for wallet#", index); if (index || index === 0) { let c = 0; - for (let wallet of this.wallets) { + for (const wallet of this.wallets) { if (c++ === index) { await wallet.fetchTransactions(); if (wallet.fetchPendingTransactions) { @@ -362,7 +377,7 @@ export class AppStorage { } } } else { - for (let wallet of this.wallets) { + for (const wallet of this.wallets) { await wallet.fetchTransactions(); if (wallet.fetchPendingTransactions) { await wallet.fetchPendingTransactions(); @@ -394,7 +409,7 @@ export class AppStorage { if (index || index === 0) { let txs = []; let c = 0; - for (let wallet of this.wallets) { + for (const wallet of this.wallets) { if (c++ === index) { txs = txs.concat(wallet.getTransactions()); } @@ -403,15 +418,15 @@ export class AppStorage { } let txs = []; - for (let wallet of this.wallets) { - let walletTransactions = wallet.getTransactions(); - for (let t of walletTransactions) { + for (const wallet of this.wallets) { + const walletTransactions = wallet.getTransactions(); + for (const t of walletTransactions) { t.walletPreferredBalanceUnit = wallet.getPreferredBalanceUnit(); } txs = txs.concat(walletTransactions); } - for (let t of txs) { + for (const t of txs) { t.sort_ts = +new Date(t.received); } @@ -429,7 +444,7 @@ export class AppStorage { */ getBalance() { let finalBalance = 0; - for (let wal of this.wallets) { + for (const wal of this.wallets) { finalBalance += wal.getBalance(); } return finalBalance; diff --git a/class/biometrics.js b/class/biometrics.js index a52b0dc0420..ad0869a9c91 100644 --- a/class/biometrics.js +++ b/class/biometrics.js @@ -1,8 +1,9 @@ -import Biometrics from 'react-native-biometrics'; -const BlueApp = require('../BlueApp'); +import Biometrics from "react-native-biometrics"; + +const BlueApp = require("../BlueApp"); export default class Biometric { - static STORAGEKEY = 'Biometrics'; + static STORAGEKEY = "Biometrics"; static FaceID = Biometrics.FaceID; static TouchID = Biometrics.TouchID; static Biometrics = Biometrics.Biometrics; @@ -31,7 +32,7 @@ export default class Biometric { const enabledBiometrics = await BlueApp.getItem(Biometric.STORAGEKEY); return !!enabledBiometrics; } catch (_e) { - await BlueApp.setItem(Biometric.STORAGEKEY, ''); + await BlueApp.setItem(Biometric.STORAGEKEY, ""); return false; } } @@ -43,14 +44,16 @@ export default class Biometric { } static async setBiometricUseEnabled(value) { - await BlueApp.setItem(Biometric.STORAGEKEY, value === true ? '1' : ''); + await BlueApp.setItem(Biometric.STORAGEKEY, value === true ? "1" : ""); } static async unlockWithBiometrics() { const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable(); if (isDeviceBiometricCapable) { try { - const isConfirmed = await Biometrics.simplePrompt({ promptMessage: 'Please confirm your identity.' }); + const isConfirmed = await Biometrics.simplePrompt({ + promptMessage: "Please confirm your identity." + }); return isConfirmed.success; } catch (_e) { return false; diff --git a/class/hd-legacy-p2pkh-wallet.js b/class/hd-legacy-p2pkh-wallet.js index 20dc554fff6..fb7717ad4cc 100644 --- a/class/hd-legacy-p2pkh-wallet.js +++ b/class/hd-legacy-p2pkh-wallet.js @@ -1,14 +1,15 @@ -import { AbstractHDWallet } from './abstract-hd-wallet'; -import Frisbee from 'frisbee'; -import { NativeModules } from 'react-native'; -import bip39 from 'bip39'; -import BigNumber from 'bignumber.js'; -import b58 from 'bs58check'; -import signer from '../models/signer'; -import { BitcoinUnit } from '../models/bitcoinUnits'; -const bitcoin = require('bitcoinjs-lib'); -const HDNode = require('bip32'); -const BlueElectrum = require('../BlueElectrum'); +import { AbstractHDWallet } from "./abstract-hd-wallet"; +import Frisbee from "frisbee"; +import { NativeModules } from "react-native"; +import bip39 from "bip39"; +import BigNumber from "bignumber.js"; +import b58 from "bs58check"; +import signer from "../models/signer"; +import { BitcoinUnit } from "../models/bitcoinUnits"; + +const bitcoin = require("bitcoinjs-lib"); +const HDNode = require("bip32"); +const BlueElectrum = require("../BlueElectrum"); const { RNRandomBytes } = NativeModules; /** @@ -17,14 +18,14 @@ const { RNRandomBytes } = NativeModules; * @see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki */ export class HDLegacyP2PKHWallet extends AbstractHDWallet { - static type = 'HDlegacyP2PKH'; - static typeReadable = 'HD Legacy (BIP44 P2PKH)'; + static type = "HDlegacyP2PKH"; + static typeReadable = "HD Legacy (BIP44 P2PKH)"; allowSend() { return true; } - allowSendMax(){ + allowSendMax() { return true; } @@ -69,14 +70,14 @@ export class HDLegacyP2PKHWallet extends AbstractHDWallet { } async generate() { - let that = this; + const that = this; return new Promise(function(resolve) { - if (typeof RNRandomBytes === 'undefined') { + if (typeof RNRandomBytes === "undefined") { // CLI/CI environment // crypto should be provided globally by test launcher return crypto.randomBytes(32, (err, buf) => { // eslint-disable-line if (err) throw err; - that.setSecret(bip39.entropyToMnemonic(buf.toString('hex'))); + that.setSecret(bip39.entropyToMnemonic(buf.toString("hex"))); resolve(); }); } @@ -84,7 +85,7 @@ export class HDLegacyP2PKHWallet extends AbstractHDWallet { // RN environment RNRandomBytes.randomBytes(32, (err, bytes) => { if (err) throw new Error(err); - let b = Buffer.from(bytes, 'base64').toString('hex'); + const b = Buffer.from(bytes, "base64").toString("hex"); that.setSecret(bip39.entropyToMnemonic(b)); resolve(); }); @@ -92,33 +93,34 @@ export class HDLegacyP2PKHWallet extends AbstractHDWallet { } generateAddresses() { - let node = bitcoin.bip32.fromBase58(this.getXpub());; - for (let index = 0; index } */ async isSequenceReplaceable() { - return (await this.getMaxUsedSequence()) < bitcoin.Transaction.DEFAULT_SEQUENCE; + return ( + (await this.getMaxUsedSequence()) < bitcoin.Transaction.DEFAULT_SEQUENCE + ); } /** @@ -80,7 +87,9 @@ export class HDSegwitBech32Transaction { * @private */ async _fetchRemoteTx() { - let result = await BlueElectrum.multiGetTransactionByTxid([this._txid || this._txDecoded.getId()]); + const result = await BlueElectrum.multiGetTransactionByTxid([ + this._txid || this._txDecoded.getId() + ]); this._remoteTx = Object.values(result)[0]; } @@ -102,9 +111,9 @@ export class HDSegwitBech32Transaction { * @returns {Promise} */ async isOurTransaction() { - if (!this._wallet) throw new Error('Wallet required for this method'); + if (!this._wallet) throw new Error("Wallet required for this method"); let found = false; - for (let tx of this._wallet.getTransactions()) { + for (const tx of this._wallet.getTransactions()) { if (tx.txid === (this._txid || this._txDecoded.getId())) { // its our transaction, and its spending transaction, which means we initiated it if (tx.value < 0) found = true; @@ -121,9 +130,9 @@ export class HDSegwitBech32Transaction { * @returns {Promise} */ async isToUsTransaction() { - if (!this._wallet) throw new Error('Wallet required for this method'); + if (!this._wallet) throw new Error("Wallet required for this method"); let found = false; - for (let tx of this._wallet.getTransactions()) { + for (const tx of this._wallet.getTransactions()) { if (tx.txid === (this._txid || this._txDecoded.getId())) { if (tx.value > 0) found = true; } @@ -143,51 +152,66 @@ export class HDSegwitBech32Transaction { * @returns {Promise<{fee: number, utxos: Array, unconfirmedUtxos: Array, changeAmount: number, feeRate: number, targets: Array}>} */ async getInfo() { - if (!this._wallet) throw new Error('Wallet required for this method'); + if (!this._wallet) throw new Error("Wallet required for this method"); if (!this._remoteTx) await this._fetchRemoteTx(); if (!this._txDecoded) await this._fetchTxhexAndDecode(); - let prevInputs = []; - for (let inp of this._txDecoded.ins) { + const prevInputs = []; + for (const inp of this._txDecoded.ins) { let reversedHash = Buffer.from(reverse(inp.hash)); - reversedHash = reversedHash.toString('hex'); + reversedHash = reversedHash.toString("hex"); prevInputs.push(reversedHash); } - let prevTransactions = await BlueElectrum.multiGetTransactionByTxid(prevInputs); + const prevTransactions = await BlueElectrum.multiGetTransactionByTxid( + prevInputs + ); // fetched, now lets count how much satoshis went in let wentIn = 0; - let utxos = []; - for (let inp of this._txDecoded.ins) { + const utxos = []; + for (const inp of this._txDecoded.ins) { let reversedHash = Buffer.from(reverse(inp.hash)); - reversedHash = reversedHash.toString('hex'); - if (prevTransactions[reversedHash] && prevTransactions[reversedHash].vout && prevTransactions[reversedHash].vout[inp.index]) { + reversedHash = reversedHash.toString("hex"); + if ( + prevTransactions[reversedHash] && + prevTransactions[reversedHash].vout && + prevTransactions[reversedHash].vout[inp.index] + ) { let value = prevTransactions[reversedHash].vout[inp.index].value; value = new BigNumber(value).multipliedBy(100000000).toNumber(); wentIn += value; - let address = SegwitBech32Wallet.witnessToAddress(inp.witness[inp.witness.length - 1]); - utxos.push({ vout: inp.index, value: value, txId: reversedHash, address: address }); + const address = SegwitBech32Wallet.witnessToAddress( + inp.witness[inp.witness.length - 1] + ); + utxos.push({ + vout: inp.index, + value: value, + txId: reversedHash, + address: address + }); } } // counting how much went into actual outputs let wasSpent = 0; - for (let outp of this._txDecoded.outs) { + for (const outp of this._txDecoded.outs) { wasSpent += +outp.value; } - let fee = wentIn - wasSpent; + const fee = wentIn - wasSpent; let feeRate = Math.floor(fee / (this._txhex.length / 2)); if (feeRate === 0) feeRate = 1; // lets take a look at change let changeAmount = 0; - let targets = []; - for (let outp of this._remoteTx.vout) { - let address = outp.scriptPubKey.addresses[0]; - let value = new BigNumber(outp.value).multipliedBy(100000000).toNumber(); + const targets = []; + for (const outp of this._remoteTx.vout) { + const address = outp.scriptPubKey.addresses[0]; + const value = new BigNumber(outp.value) + .multipliedBy(100000000) + .toNumber(); if (this._wallet.weOwnAddress(address)) { changeAmount += value; } else { @@ -197,16 +221,18 @@ export class HDSegwitBech32Transaction { } // lets find outputs we own that current transaction creates. can be used in CPFP - let unconfirmedUtxos = []; - for (let outp of this._remoteTx.vout) { - let address = outp.scriptPubKey.addresses[0]; - let value = new BigNumber(outp.value).multipliedBy(100000000).toNumber(); + const unconfirmedUtxos = []; + for (const outp of this._remoteTx.vout) { + const address = outp.scriptPubKey.addresses[0]; + const value = new BigNumber(outp.value) + .multipliedBy(100000000) + .toNumber(); if (this._wallet.weOwnAddress(address)) { unconfirmedUtxos.push({ vout: outp.n, value: value, txId: this._txid || this._txDecoded.getId(), - address: address, + address: address }); } } @@ -221,12 +247,17 @@ export class HDSegwitBech32Transaction { * @returns {Promise} */ async canCancelTx() { - if (!this._wallet) throw new Error('Wallet required for this method'); + if (!this._wallet) throw new Error("Wallet required for this method"); if (!this._txDecoded) await this._fetchTxhexAndDecode(); // if theres at least one output we dont own - we can cancel this transaction! - for (let outp of this._txDecoded.outs) { - if (!this._wallet.weOwnAddress(SegwitBech32Wallet.scriptPubKeyToAddress(outp.script))) return true; + for (const outp of this._txDecoded.outs) { + if ( + !this._wallet.weOwnAddress( + SegwitBech32Wallet.scriptPubKeyToAddress(outp.script) + ) + ) + return true; } return false; @@ -241,20 +272,21 @@ export class HDSegwitBech32Transaction { * @returns {Promise<{outputs: Array, tx: Transaction, inputs: Array, fee: Number}>} */ async createRBFcancelTx(newFeerate) { - if (!this._wallet) throw new Error('Wallet required for this method'); + if (!this._wallet) throw new Error("Wallet required for this method"); if (!this._remoteTx) await this._fetchRemoteTx(); - let { feeRate, utxos } = await this.getInfo(); + const { feeRate, utxos } = await this.getInfo(); - if (newFeerate <= feeRate) throw new Error('New feerate should be bigger than the old one'); - let myAddress = await this._wallet.getAddressForTransaction(); + if (newFeerate <= feeRate) + throw new Error("New feerate should be bigger than the old one"); + const myAddress = await this._wallet.getAddressForTransaction(); return this._wallet.createTransaction( utxos, [{ address: myAddress }], newFeerate, /* meaningless in this context */ myAddress, - (await this.getMaxUsedSequence()) + 1, + (await this.getMaxUsedSequence()) + 1 ); } @@ -266,13 +298,14 @@ export class HDSegwitBech32Transaction { * @returns {Promise<{outputs: Array, tx: Transaction, inputs: Array, fee: Number}>} */ async createRBFbumpFee(newFeerate) { - if (!this._wallet) throw new Error('Wallet required for this method'); + if (!this._wallet) throw new Error("Wallet required for this method"); if (!this._remoteTx) await this._fetchRemoteTx(); - let { feeRate, targets, changeAmount, utxos } = await this.getInfo(); + const { feeRate, targets, changeAmount, utxos } = await this.getInfo(); - if (newFeerate <= feeRate) throw new Error('New feerate should be bigger than the old one'); - let myAddress = await this._wallet.getAddressForTransaction(); + if (newFeerate <= feeRate) + throw new Error("New feerate should be bigger than the old one"); + const myAddress = await this._wallet.getAddressForTransaction(); if (changeAmount === 0) delete targets[0].value; // looks like this was sendMAX transaction (because there was no change), so we cant reuse amount in this @@ -285,7 +318,13 @@ export class HDSegwitBech32Transaction { // not checking emptiness on purpose: it could unpredictably generate too far address because of unconfirmed tx. } - return this._wallet.createTransaction(utxos, targets, newFeerate, myAddress, (await this.getMaxUsedSequence()) + 1); + return this._wallet.createTransaction( + utxos, + targets, + newFeerate, + myAddress, + (await this.getMaxUsedSequence()) + 1 + ); } /** @@ -296,13 +335,14 @@ export class HDSegwitBech32Transaction { * @returns {Promise<{outputs: Array, tx: Transaction, inputs: Array, fee: Number}>} */ async createCPFPbumpFee(newFeerate) { - if (!this._wallet) throw new Error('Wallet required for this method'); + if (!this._wallet) throw new Error("Wallet required for this method"); if (!this._remoteTx) await this._fetchRemoteTx(); - let { feeRate, fee: oldFee, unconfirmedUtxos } = await this.getInfo(); + const { feeRate, fee: oldFee, unconfirmedUtxos } = await this.getInfo(); - if (newFeerate <= feeRate) throw new Error('New feerate should be bigger than the old one'); - let myAddress = await this._wallet.getAddressForTransaction(); + if (newFeerate <= feeRate) + throw new Error("New feerate should be bigger than the old one"); + const myAddress = await this._wallet.getAddressForTransaction(); // calculating feerate for CPFP tx so that average between current and CPFP tx will equal newFeerate. // this works well if both txs are +/- equal size in bytes @@ -315,9 +355,10 @@ export class HDSegwitBech32Transaction { [{ address: myAddress }], targetFeeRate + add, myAddress, - HDSegwitBech32Wallet.defaultRBFSequence, + HDSegwitBech32Wallet.defaultRBFSequence ); - let combinedFeeRate = (oldFee + fee) / (this._txhex.length / 2 + tx.toHex().length / 2); // avg + const combinedFeeRate = + (oldFee + fee) / (this._txhex.length / 2 + tx.toHex().length / 2); // avg if (Math.round(combinedFeeRate) < newFeerate) { add *= 2; if (!add) add = 2; diff --git a/class/hd-segwit-bech32-wallet.js b/class/hd-segwit-bech32-wallet.js index 40e9cdbce83..9dd3237aa06 100644 --- a/class/hd-segwit-bech32-wallet.js +++ b/class/hd-segwit-bech32-wallet.js @@ -1,13 +1,14 @@ -import { AbstractHDWallet } from './abstract-hd-wallet'; -import { NativeModules } from 'react-native'; -import bip39 from 'bip39'; -import BigNumber from 'bignumber.js'; -import b58 from 'bs58check'; -const bitcoin = require('bitcoinjs-lib'); -const BlueElectrum = require('../BlueElectrum'); -const HDNode = require('bip32'); -const coinSelectAccumulative = require('coinselect/accumulative'); -const coinSelectSplit = require('coinselect/split'); +import { AbstractHDWallet } from "./abstract-hd-wallet"; +import { NativeModules } from "react-native"; +import bip39 from "bip39"; +import BigNumber from "bignumber.js"; +import b58 from "bs58check"; + +const bitcoin = require("bitcoinjs-lib"); +const BlueElectrum = require("../BlueElectrum"); +const HDNode = require("bip32"); +const coinSelectAccumulative = require("coinselect/accumulative"); +const coinSelectSplit = require("coinselect/split"); const { RNRandomBytes } = NativeModules; @@ -17,8 +18,8 @@ const { RNRandomBytes } = NativeModules; * @see https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki */ export class HDSegwitBech32Wallet extends AbstractHDWallet { - static type = 'HDsegwitBech32'; - static typeReadable = 'HD SegWit (BIP84 Bech32 Native)'; + static type = "HDsegwitBech32"; + static typeReadable = "HD SegWit (BIP84 Bech32 Native)"; static defaultRBFSequence = 2147483648; // 1 << 31, minimum for replaceable transactions as per BIP68 constructor() { @@ -39,7 +40,7 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { * @inheritDoc */ timeToRefreshTransaction() { - for (let tx of this.getTransactions()) { + for (const tx of this.getTransactions()) { if (tx.confirmations < 7) return true; } return false; @@ -50,14 +51,14 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { } async generate() { - let that = this; + const that = this; return new Promise(function(resolve) { - if (typeof RNRandomBytes === 'undefined') { + if (typeof RNRandomBytes === "undefined") { // CLI/CI environment // crypto should be provided globally by test launcher return crypto.randomBytes(32, (err, buf) => { // eslint-disable-line if (err) throw err; - that.setSecret(bip39.entropyToMnemonic(buf.toString('hex'))); + that.setSecret(bip39.entropyToMnemonic(buf.toString("hex"))); resolve(); }); } @@ -65,7 +66,7 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { // RN environment RNRandomBytes.randomBytes(32, (err, bytes) => { if (err) throw new Error(err); - let b = Buffer.from(bytes, 'base64').toString('hex'); + const b = Buffer.from(bytes, "base64").toString("hex"); that.setSecret(bip39.entropyToMnemonic(b)); resolve(); }); @@ -92,7 +93,7 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { _getNodeAddressByIndex(index) { index = index * 1; // cast to int - return this._address[index] + return this._address[index]; } generateAddresses() { @@ -102,13 +103,15 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { this._node0 = hdNode.derive(0); } for (let index = 0; index < this.num_addresses; index++) { - let address = this.constructor._nodeToBech32SegwitAddress(this._node0.derive(index)); + const address = this.constructor._nodeToBech32SegwitAddress( + this._node0.derive(index) + ); this._address.push(address); this._address_to_wif_cache[address] = this._getWIFByIndex(index); this._addr_balances[address] = { total: 0, c: 0, - u: 0, + u: 0 }; console.warn(this._addr_balances); } @@ -123,7 +126,9 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { this._node0 = hdNode.derive(0); } console.warn(this._node0.derive(index).publicKey); - console.warn(this.constructor._nodeToBech32SegwitAddress(this._node0.derive(index))); + console.warn( + this.constructor._nodeToBech32SegwitAddress(this._node0.derive(index)) + ); return this._node0.derive(index).publicKey; } @@ -149,7 +154,7 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { // bitcoinjs does not support zpub yet, so we just convert it from xpub let data = b58.decode(xpub); data = data.slice(4); - data = Buffer.concat([Buffer.from('04b24746', 'hex'), data]); + data = Buffer.concat([Buffer.from("04b24746", "hex"), data]); this._xpub = b58.encode(data); return this._xpub; @@ -157,22 +162,22 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { _getDerivationPathByAddress(address) { const path = "m/84'/0'/0'/0/"; - let index = this._address.indexOf(address); + const index = this._address.indexOf(address); if (index === -1) return false; return path + index; } _getPubkeyByAddress(address) { - let index = this._address.indexOf(address); + const index = this._address.indexOf(address); if (index === -1) return false; return this._getNodePubkeyByIndex(index); - } + } /** * @deprecated */ createTx(utxos, amount, fee, address) { - throw new Error('Deprecated'); + throw new Error("Deprecated"); } /** @@ -185,26 +190,33 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { * @param skipSigning {boolean} Whether we should skip signing, use returned `psbt` in that case * @returns {{outputs: Array, tx: Transaction, inputs: Array, fee: Number, psbt: Psbt}} */ - createTransaction(utxos, targets, feeRate, changeAddress, sequence, skipSigning = false) { - if (!changeAddress) throw new Error('No change address provided'); + createTransaction( + utxos, + targets, + feeRate, + changeAddress, + sequence, + skipSigning = false + ) { + if (!changeAddress) throw new Error("No change address provided"); sequence = sequence || HDSegwitBech32Wallet.defaultRBFSequence; let algo = coinSelectAccumulative; if (targets.length === 1 && targets[0] && !targets[0].value) { // we want to send MAX algo = coinSelectSplit; } - let { inputs, outputs, fee } = algo(utxos, targets, feeRate); + 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'); + throw new Error("Not enough balance. Try sending smaller amount"); } - let psbt = new bitcoin.Psbt(); + const psbt = new bitcoin.Psbt(); let c = 0; - let keypairs = {}; - let values = {}; + const keypairs = {}; + const values = {}; inputs.forEach(input => { let keyPair; @@ -217,14 +229,15 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { c++; if (!skipSigning) { // skiping signing related stuff - if (!input.address || !this._getWifForAddress(input.address)) throw new Error('Internal error: no address or WIF to sign input'); + if (!input.address || !this._getWifForAddress(input.address)) + throw new Error("Internal error: no address or WIF to sign input"); } - let pubkey = this._getPubkeyByAddress(input.address); - let masterFingerprint = Buffer.from([0x00, 0x00, 0x00, 0x00]); + const pubkey = this._getPubkeyByAddress(input.address); + const masterFingerprint = Buffer.from([0x00, 0x00, 0x00, 0x00]); // this is not correct fingerprint, as we dont know real fingerprint - we got zpub with 84/0, but fingerpting // should be from root. basically, fingerprint should be provided from outside by user when importing zpub - let path = this._getDerivationPathByAddress(input.address); - const p2wpkh = bitcoin.payments.p2wpkh({ pubkey }) + const path = this._getDerivationPathByAddress(input.address); + const p2wpkh = bitcoin.payments.p2wpkh({ pubkey }); psbt.addInput({ hash: input.txid, index: input.vout, @@ -233,13 +246,13 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { { masterFingerprint, path, - pubkey, - }, + pubkey + } ], witnessUtxo: { script: p2wpkh.output, - value: input.value, - }, + value: input.value + } }); }); @@ -251,24 +264,24 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { output.address = changeAddress; } - let path = this._getDerivationPathByAddress(output.address); - let pubkey = this._getPubkeyByAddress(output.address); - let masterFingerprint = Buffer.from([0x00, 0x00, 0x00, 0x00]); + const path = this._getDerivationPathByAddress(output.address); + const pubkey = this._getPubkeyByAddress(output.address); + const masterFingerprint = Buffer.from([0x00, 0x00, 0x00, 0x00]); // this is not correct fingerprint, as we dont know realfingerprint - we got zpub with 84/0, but fingerpting // should be from root. basically, fingerprint should be provided from outside by user when importing zpub - let outputData = { + const outputData = { address: output.address, - value: output.value, + value: output.value }; if (change) { - outputData['bip32Derivation'] = [ + outputData["bip32Derivation"] = [ { masterFingerprint, path, - pubkey, - }, + pubkey + } ]; } @@ -312,7 +325,7 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { */ static _nodeToBech32SegwitAddress(hdNode) { return bitcoin.payments.p2wpkh({ - pubkey: hdNode.publicKey, + pubkey: hdNode.publicKey }).address; } @@ -325,7 +338,7 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { static _zpubToXpub(zpub) { let data = b58.decode(zpub); data = data.slice(4); - data = Buffer.concat([Buffer.from('a40c86fa', 'hex'), data]); + data = Buffer.concat([Buffer.from("a40c86fa", "hex"), data]); return b58.encode(data); } @@ -337,9 +350,9 @@ export class HDSegwitBech32Wallet extends AbstractHDWallet { * @returns {Promise} */ async broadcastTx(txhex) { - let broadcast = await BlueElectrum.broadcastV2(txhex); + const broadcast = await BlueElectrum.broadcastV2(txhex); console.log({ broadcast }); - if (broadcast.indexOf('successfully') !== -1) return true; + if (broadcast.indexOf("successfully") !== -1) return true; return broadcast.length === 64; // this means return string is txid (precise length), so it was broadcasted ok } } diff --git a/class/hd-segwit-p2sh-wallet.js b/class/hd-segwit-p2sh-wallet.js index c356727e1ae..2e0926327d1 100644 --- a/class/hd-segwit-p2sh-wallet.js +++ b/class/hd-segwit-p2sh-wallet.js @@ -1,14 +1,15 @@ -import { AbstractHDWallet } from './abstract-hd-wallet'; -import Frisbee from 'frisbee'; -import { NativeModules } from 'react-native'; -import bip39 from 'bip39'; -import BigNumber from 'bignumber.js'; -import b58 from 'bs58check'; -import signer from '../models/signer'; -import { BitcoinUnit } from '../models/bitcoinUnits'; -const bitcoin = require('bitcoinjs-lib'); -const HDNode = require('bip32'); -const BlueElectrum = require('../BlueElectrum'); +import { AbstractHDWallet } from "./abstract-hd-wallet"; +import Frisbee from "frisbee"; +import { NativeModules } from "react-native"; +import bip39 from "bip39"; +import BigNumber from "bignumber.js"; +import b58 from "bs58check"; +import signer from "../models/signer"; +import { BitcoinUnit } from "../models/bitcoinUnits"; + +const bitcoin = require("bitcoinjs-lib"); +const HDNode = require("bip32"); +const BlueElectrum = require("../BlueElectrum"); const { RNRandomBytes } = NativeModules; @@ -19,9 +20,10 @@ const { RNRandomBytes } = NativeModules; */ function ypubToXpub(ypub) { let data = b58.decode(ypub); - if (data.readUInt32BE() !== 0x049d7cb2) throw new Error('Not a valid ypub extended key!'); + if (data.readUInt32BE() !== 0x049d7cb2) + throw new Error("Not a valid ypub extended key!"); data = data.slice(4); - data = Buffer.concat([Buffer.from('a40c86fa', 'hex'), data]); + data = Buffer.concat([Buffer.from("a40c86fa", "hex"), data]); return b58.encode(data); } @@ -33,7 +35,7 @@ function ypubToXpub(ypub) { */ function nodeToP2shSegwitAddress(hdNode) { const { address } = bitcoin.payments.p2sh({ - redeem: bitcoin.payments.p2wpkh({ pubkey: hdNode.publicKey }), + redeem: bitcoin.payments.p2wpkh({ pubkey: hdNode.publicKey }) }); return address; } @@ -44,26 +46,26 @@ function nodeToP2shSegwitAddress(hdNode) { * @see https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki */ export class HDSegwitP2SHWallet extends AbstractHDWallet { - static type = 'HDsegwitP2SH'; - static typeReadable = 'HD SegWit (BIP49 P2SH)'; + static type = "HDsegwitP2SH"; + static typeReadable = "HD SegWit (BIP49 P2SH)"; allowSend() { return true; } - allowSendMax(){ + allowSendMax() { return true; } async generate() { - let that = this; + const that = this; return new Promise(function(resolve) { - if (typeof RNRandomBytes === 'undefined') { + if (typeof RNRandomBytes === "undefined") { // CLI/CI environment // crypto should be provided globally by test launcher return crypto.randomBytes(32, (err, buf) => { // eslint-disable-line if (err) throw err; - that.setSecret(bip39.entropyToMnemonic(buf.toString('hex'))); + that.setSecret(bip39.entropyToMnemonic(buf.toString("hex"))); resolve(); }); } @@ -71,7 +73,7 @@ export class HDSegwitP2SHWallet extends AbstractHDWallet { // RN environment RNRandomBytes.randomBytes(32, (err, bytes) => { if (err) throw new Error(err); - let b = Buffer.from(bytes, 'base64').toString('hex'); + const b = Buffer.from(bytes, "base64").toString("hex"); that.setSecret(bip39.entropyToMnemonic(b)); resolve(); }); @@ -117,7 +119,7 @@ export class HDSegwitP2SHWallet extends AbstractHDWallet { // bitcoinjs does not support ypub yet, so we just convert it from xpub let data = b58.decode(xpub); data = data.slice(4); - data = Buffer.concat([Buffer.from('049d7cb2', 'hex'), data]); + data = Buffer.concat([Buffer.from("049d7cb2", "hex"), data]); this._xpub = b58.encode(data); return this._xpub; @@ -125,18 +127,18 @@ export class HDSegwitP2SHWallet extends AbstractHDWallet { generateAddresses() { if (!this._node0) { - const xpub = ypubToXpub(this.getXpub()); - const hdNode = HDNode.fromBase58(xpub); - this._node0 = hdNode.derive(0); + const xpub = ypubToXpub(this.getXpub()); + const hdNode = HDNode.fromBase58(xpub); + this._node0 = hdNode.derive(0); } - for (let index = 0; index { // eslint-disable-line @@ -52,7 +54,7 @@ export class LegacyWallet extends AbstractWallet { that.secret = bitcoin.ECPair.makeRandom({ rng: function(length) { return buf; - }, + } }).toWIF(); resolve(); }); @@ -63,9 +65,9 @@ export class LegacyWallet extends AbstractWallet { if (err) throw new Error(err); that.secret = bitcoin.ECPair.makeRandom({ rng: function(length) { - let b = Buffer.from(bytes, 'base64'); + const b = Buffer.from(bytes, "base64"); return b; - }, + } }).toWIF(); resolve(); }); @@ -80,9 +82,9 @@ export class LegacyWallet extends AbstractWallet { if (this._address) return this._address; let address; try { - let keyPair = bitcoin.ECPair.fromWIF(this.secret); + const keyPair = bitcoin.ECPair.fromWIF(this.secret); address = bitcoin.payments.p2pkh({ - pubkey: keyPair.publicKey, + pubkey: keyPair.publicKey }).address; } catch (err) { return false; @@ -90,7 +92,7 @@ export class LegacyWallet extends AbstractWallet { this._address = address; return this._address; - } + } /** * Fetches balance of the Wallet via API. @@ -99,8 +101,8 @@ export class LegacyWallet extends AbstractWallet { * @returns {Promise.} */ async fetchBalance() { - try { - let balance = await BlueElectrum.getBalanceByAddress(this.getAddress()); + try { + const balance = await BlueElectrum.getBalanceByAddress(this.getAddress()); this.balance = balance.confirmed + balance.unconfirmed; this.unconfirmed_balance = balance.unconfirmed; this._lastBalanceFetch = +new Date(); @@ -117,26 +119,31 @@ export class LegacyWallet extends AbstractWallet { async fetchUtxo() { try { this.utxo = []; - let utxos = await BlueElectrum.multiGetUtxoByAddress([this.getAddress()]); + const utxos = await BlueElectrum.multiGetUtxoByAddress([ + this.getAddress() + ]); this.utxo = utxos; } catch (err) { console.warn(err.message); } } - /** + /** * Fetches transactions via API. Returns VOID. * Use getter to get the actual list. * * @return {Promise.} */ async fetchTransactions() { - let txids_to_update = [] + const txids_to_update = []; try { this._lastTxFetch = +new Date(); - let txids = await BlueElectrum.getTransactionsByAddress(this.getAddress()); - for (let tx of txids) { - if (!this.transactionConfirmed(tx.tx_hash)) txids_to_update.push(tx.tx_hash); + const txids = await BlueElectrum.getTransactionsByAddress( + this.getAddress() + ); + for (const tx of txids) { + if (!this.transactionConfirmed(tx.tx_hash)) + txids_to_update.push(tx.tx_hash); } await this._update_unconfirmed_tx(txids_to_update); } catch (Err) { @@ -166,14 +173,23 @@ export class LegacyWallet extends AbstractWallet { */ createTx(utxos, amount, fee, toAddress, memo) { // transforming UTXOs fields to how module expects it - for (let u of utxos) { + for (const u of utxos) { u.confirmations = 6; // hack to make module accept 0 confirmation u.amount = u.amount.dividedBy(100000000); u.amount = u.amount.toString(10); } // console.log('creating legacy tx ', amount, ' with fee ', fee, 'secret=', this.getSecret(), 'from address', this.getAddress()); - let amountPlusFee = parseFloat(new BigNumber(amount).plus(fee).toString(10)); - return signer.createTransaction(utxos, toAddress, amountPlusFee, fee, this.getSecret(), this.getAddress()); + const amountPlusFee = parseFloat( + new BigNumber(amount).plus(fee).toString(10) + ); + return signer.createTransaction( + utxos, + toAddress, + amountPlusFee, + fee, + this.getSecret(), + this.getAddress() + ); } getLatestTransactionTime() { @@ -181,7 +197,7 @@ export class LegacyWallet extends AbstractWallet { return 0; } let max = 0; - for (let tx of this.getTransactions()) { + for (const tx of this.getTransactions()) { max = Math.max(new Date(tx.received) * 1, max); } @@ -191,16 +207,16 @@ export class LegacyWallet extends AbstractWallet { getRandomBlockcypherToken() { return (array => { for (let i = array.length - 1; i > 0; i--) { - let j = Math.floor(Math.random() * (i + 1)); + const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array[0]; })([ - '0326b7107b4149559d18ce80612ef812', - 'a133eb7ccacd4accb80cb1225de4b155', - '7c2b1628d27b4bd3bf8eaee7149c577f', - 'f1e5a02b9ec84ec4bc8db2349022e5f5', - 'e5926dbeb57145979153adc41305b183', + "0326b7107b4149559d18ce80612ef812", + "a133eb7ccacd4accb80cb1225de4b155", + "7c2b1628d27b4bd3bf8eaee7149c577f", + "f1e5a02b9ec84ec4bc8db2349022e5f5", + "e5926dbeb57145979153adc41305b183" ]); } @@ -214,7 +230,7 @@ export class LegacyWallet extends AbstractWallet { } transactionConfirmed(txid) { - for (let transaction of this.transactions) { + for (const transaction of this.transactions) { if (txid === transaction.txid) return true; } return false; @@ -225,34 +241,32 @@ export class LegacyWallet extends AbstractWallet { } async _update_unconfirmed_tx(txid_list) { - try{ - let txs_full = await BlueElectrum.multiGetTransactionsFullByTxid(txid_list); - let unconfirmed_transactions = [] - for (let tx of txs_full) { + try { + const txs_full = await BlueElectrum.multiGetTransactionsFullByTxid( + txid_list + ); + const unconfirmed_transactions = []; + for (const tx of txs_full) { let value = 0; - for (let input of tx.inputs) { - if (!input.txid) continue; // coinbase - if (this.weOwnAddress(input.addresses[0])) value -= input.value; - } - for (let output of tx.outputs) { - if (!output.addresses) continue; // OP_RETURN - if (this.weOwnAddress(output.addresses[0])) value += output.value; - } - tx.value = new BigNumber(value).multipliedBy(100000000).toNumber();; - if (tx.time) - tx.received = new Date(tx.time * 1000).toISOString(); - else - tx.received = new Date().toISOString(); - tx.walletLabel = this.label - if (!tx.confirmations) tx.confirmations = 0; - if (tx.confirmations < 6 ) - unconfirmed_transactions.push(tx); - else - this.transactions.push(tx); + for (const input of tx.inputs) { + if (!input.txid) continue; // coinbase + if (this.weOwnAddress(input.addresses[0])) value -= input.value; + } + for (const output of tx.outputs) { + if (!output.addresses) continue; // OP_RETURN + if (this.weOwnAddress(output.addresses[0])) value += output.value; + } + tx.value = new BigNumber(value).multipliedBy(100000000).toNumber(); + if (tx.time) tx.received = new Date(tx.time * 1000).toISOString(); + else tx.received = new Date().toISOString(); + tx.walletLabel = this.label; + if (!tx.confirmations) tx.confirmations = 0; + if (tx.confirmations < 6) unconfirmed_transactions.push(tx); + else this.transactions.push(tx); } this.unconfirmed_transactions = unconfirmed_transactions; // all unconfirmed transactions will be updated } catch (err) { - console.warn(err.message); + console.warn(err.message); } } } diff --git a/class/onAppLaunch.js b/class/onAppLaunch.js index f257422ce61..6ed028d7155 100644 --- a/class/onAppLaunch.js +++ b/class/onAppLaunch.js @@ -1,13 +1,16 @@ -import AsyncStorage from '@react-native-community/async-storage'; -const BlueApp = require('../BlueApp'); +import AsyncStorage from "@react-native-community/async-storage"; + +const BlueApp = require("../BlueApp"); export default class OnAppLaunch { - static STORAGE_KEY = 'ONAPP_LAUNCH_SELECTED_DEFAULT_WALLET_KEY'; + static STORAGE_KEY = "ONAPP_LAUNCH_SELECTED_DEFAULT_WALLET_KEY"; static async isViewAllWalletsEnabled() { try { - const selectedDefaultWallet = await AsyncStorage.getItem(OnAppLaunch.STORAGE_KEY); - return selectedDefaultWallet === '' || selectedDefaultWallet === null; + const selectedDefaultWallet = await AsyncStorage.getItem( + OnAppLaunch.STORAGE_KEY + ); + return selectedDefaultWallet === "" || selectedDefaultWallet === null; } catch (_e) { return true; } @@ -21,17 +24,21 @@ export default class OnAppLaunch { await OnAppLaunch.setSelectedDefaultWallet(firstWallet.getID()); } } else { - await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, ''); + await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, ""); } } static async getSelectedDefaultWallet() { let selectedWallet = false; try { - const selectedWalletID = JSON.parse(await AsyncStorage.getItem(OnAppLaunch.STORAGE_KEY)); - selectedWallet = BlueApp.getWallets().find(wallet => wallet.getID() === selectedWalletID); + const selectedWalletID = JSON.parse( + await AsyncStorage.getItem(OnAppLaunch.STORAGE_KEY) + ); + selectedWallet = BlueApp.getWallets().find( + wallet => wallet.getID() === selectedWalletID + ); if (!selectedWallet) { - await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, ''); + await AsyncStorage.setItem(OnAppLaunch.STORAGE_KEY, ""); } } catch (_e) { return false; diff --git a/class/quickActions.js b/class/quickActions.js index 5a080596bd2..997d6039dca 100644 --- a/class/quickActions.js +++ b/class/quickActions.js @@ -1,5 +1,5 @@ -import QuickActions from 'react-native-quick-actions'; -import { Platform } from 'react-native'; +import QuickActions from "react-native-quick-actions"; +import { Platform } from "react-native"; export default class DeviceQuickActions { static shared = new DeviceQuickActions(); @@ -19,20 +19,24 @@ export default class DeviceQuickActions { } QuickActions.isSupported((error, supported) => { if (supported && error === null) { - let shortcutItems = []; - const loc = require('../loc/'); + const shortcutItems = []; + const loc = require("../loc/"); for (const wallet of DeviceQuickActions.shared.wallets) { shortcutItems.push({ - type: 'Wallets', // Required + type: "Wallets", // Required title: wallet.getLabel(), // Optional, if empty, `type` will be used instead subtitle: wallet.hideBalance || wallet.getBalance() <= 0 - ? '' - : loc.formatBalance(Number(wallet.getBalance()), wallet.getPreferredBalanceUnit(), true), + ? "" + : loc.formatBalance( + Number(wallet.getBalance()), + wallet.getPreferredBalanceUnit(), + true + ), userInfo: { - url: `veleswallet://wallet/${wallet.getID()}`, // Provide any custom data like deep linking URL + url: `veleswallet://wallet/${wallet.getID()}` // Provide any custom data like deep linking URL }, - icon: Platform.select({ android: 'quickactions', ios: 'bookmark' }), + icon: Platform.select({ android: "quickactions", ios: "bookmark" }) }); } QuickActions.setShortcutItems(shortcutItems); diff --git a/class/segwit-bech-wallet.js b/class/segwit-bech-wallet.js index a2db477bd42..97f52872476 100644 --- a/class/segwit-bech-wallet.js +++ b/class/segwit-bech-wallet.js @@ -1,17 +1,18 @@ -import { LegacyWallet } from './legacy-wallet'; -const bitcoin = require('bitcoinjs-lib'); +import { LegacyWallet } from "./legacy-wallet"; + +const bitcoin = require("bitcoinjs-lib"); export class SegwitBech32Wallet extends LegacyWallet { - static type = 'segwitBech32'; - static typeReadable = 'P2 WPKH'; + static type = "segwitBech32"; + static typeReadable = "P2 WPKH"; getAddress() { if (this._address) return this._address; let address; try { - let keyPair = bitcoin.ECPair.fromWIF(this.secret); + const keyPair = bitcoin.ECPair.fromWIF(this.secret); address = bitcoin.payments.p2wpkh({ - pubkey: keyPair.publicKey, + pubkey: keyPair.publicKey }).address; } catch (err) { return false; @@ -22,10 +23,10 @@ export class SegwitBech32Wallet extends LegacyWallet { } static witnessToAddress(witness) { - const pubKey = Buffer.from(witness, 'hex'); + const pubKey = Buffer.from(witness, "hex"); return bitcoin.payments.p2wpkh({ pubkey: pubKey, - network: bitcoin.networks.bitcoin, + network: bitcoin.networks.bitcoin }).address; } @@ -36,12 +37,12 @@ export class SegwitBech32Wallet extends LegacyWallet { * @returns {boolean|string} Either bech32 address or false */ static scriptPubKeyToAddress(scriptPubKey) { - const scriptPubKey2 = Buffer.from(scriptPubKey, 'hex'); + const scriptPubKey2 = Buffer.from(scriptPubKey, "hex"); let ret; try { ret = bitcoin.payments.p2wpkh({ output: scriptPubKey2, - network: bitcoin.networks.bitcoin, + network: bitcoin.networks.bitcoin }).address; } catch (_) { return false; diff --git a/class/segwit-p2sh-wallet.js b/class/segwit-p2sh-wallet.js index cab43bdd840..e4e4fe606cb 100644 --- a/class/segwit-p2sh-wallet.js +++ b/class/segwit-p2sh-wallet.js @@ -1,7 +1,8 @@ -import { LegacyWallet } from './legacy-wallet'; -const bitcoin = require('bitcoinjs-lib'); -const signer = require('../models/signer'); -const BigNumber = require('bignumber.js'); +import { LegacyWallet } from "./legacy-wallet"; + +const bitcoin = require("bitcoinjs-lib"); +const signer = require("../models/signer"); +const BigNumber = require("bignumber.js"); /** * Creates Segwit P2SH Bitcoin address @@ -13,21 +14,21 @@ function pubkeyToP2shSegwitAddress(pubkey, network) { network = network || bitcoin.networks.bitcoin; const { address } = bitcoin.payments.p2sh({ redeem: bitcoin.payments.p2wpkh({ pubkey, network }), - network, + network }); return address; } export class SegwitP2SHWallet extends LegacyWallet { - static type = 'segwitP2SH'; - static typeReadable = 'SegWit (P2SH)'; + static type = "segwitP2SH"; + static typeReadable = "SegWit (P2SH)"; allowRBF() { return true; } static witnessToAddress(witness) { - const pubKey = Buffer.from(witness, 'hex'); + const pubKey = Buffer.from(witness, "hex"); return pubkeyToP2shSegwitAddress(pubKey); } @@ -38,12 +39,12 @@ export class SegwitP2SHWallet extends LegacyWallet { * @returns {boolean|string} Either p2sh address or false */ static scriptPubKeyToAddress(scriptPubKey) { - const scriptPubKey2 = Buffer.from(scriptPubKey, 'hex'); + const scriptPubKey2 = Buffer.from(scriptPubKey, "hex"); let ret; try { ret = bitcoin.payments.p2sh({ output: scriptPubKey2, - network: bitcoin.networks.bitcoin, + network: bitcoin.networks.bitcoin }).address; } catch (_) { return false; @@ -55,10 +56,10 @@ export class SegwitP2SHWallet extends LegacyWallet { if (this._address) return this._address; let address; try { - let keyPair = bitcoin.ECPair.fromWIF(this.secret); - let pubKey = keyPair.publicKey; + const keyPair = bitcoin.ECPair.fromWIF(this.secret); + const pubKey = keyPair.publicKey; if (!keyPair.compressed) { - console.warn('only compressed public keys are good for segwit'); + console.warn("only compressed public keys are good for segwit"); return false; } address = pubkeyToP2shSegwitAddress(pubKey); @@ -88,13 +89,23 @@ export class SegwitP2SHWallet extends LegacyWallet { sequence = 0; } // transforming UTXOs fields to how module expects it - for (let u of utxos) { + for (const u of utxos) { u.amount = u.amount.dividedBy(100000000); u.amount = u.amount.toString(10); } // console.log('creating tx ', amount, ' with fee ', fee, 'secret=', this.getSecret(), 'from address', this.getAddress()); - let amountPlusFee = parseFloat(new BigNumber(amount).plus(fee).toString(10)); + const amountPlusFee = parseFloat( + new BigNumber(amount).plus(fee).toString(10) + ); // to compensate that module substracts fee from amount - return signer.createSegwitTransaction(utxos, address, amountPlusFee, fee, this.getSecret(), this.getAddress(), sequence); + return signer.createSegwitTransaction( + utxos, + address, + amountPlusFee, + fee, + this.getSecret(), + this.getAddress(), + sequence + ); } } diff --git a/class/walletGradient.js b/class/walletGradient.js index 9bbbfe3fe20..5b7d82d41d8 100644 --- a/class/walletGradient.js +++ b/class/walletGradient.js @@ -1,17 +1,17 @@ // import { LegacyWallet } from './legacy-wallet'; -import { HDSegwitP2SHWallet } from './hd-segwit-p2sh-wallet'; -import { HDLegacyP2PKHWallet } from './hd-legacy-p2pkh-wallet'; -import { WatchOnlyWallet } from './watch-only-wallet'; -import { HDSegwitBech32Wallet } from './hd-segwit-bech32-wallet'; +import { HDSegwitP2SHWallet } from "./hd-segwit-p2sh-wallet"; +import { HDLegacyP2PKHWallet } from "./hd-legacy-p2pkh-wallet"; +import { WatchOnlyWallet } from "./watch-only-wallet"; +import { HDSegwitBech32Wallet } from "./hd-segwit-bech32-wallet"; export default class WalletGradient { - static hdLegacyP2PKHWallet = ['#e4b99c', '#e08a50']; - static hdSegwitBech32Wallet = ['#e36dfa', '#bd10e0']; - static hdSegwitP2SHWallet = ['#f19b7e', '#f43d00']; - static watchOnlyWallet = ['#7d7d7d', '#4a4a4a']; - static legacyWallet = ['#40fad1', '#15be98']; - static defaultGradients = ['#aeed6a', '#8aea23']; - static createWallet = ['rgba(38, 38, 38, 0.9)', 'rgba(38, 38, 38, 0.9)']; + static hdLegacyP2PKHWallet = ["#e4b99c", "#e08a50"]; + static hdSegwitBech32Wallet = ["#e36dfa", "#bd10e0"]; + static hdSegwitP2SHWallet = ["#f19b7e", "#f43d00"]; + static watchOnlyWallet = ["#7d7d7d", "#4a4a4a"]; + static legacyWallet = ["#40fad1", "#15be98"]; + static defaultGradients = ["#aeed6a", "#8aea23"]; + static createWallet = ["rgba(38, 38, 38, 0.9)", "rgba(38, 38, 38, 0.9)"]; static gradientsFor(type) { let gradient; @@ -28,7 +28,7 @@ export default class WalletGradient { case HDSegwitBech32Wallet.type: gradient = WalletGradient.hdSegwitBech32Wallet; break; - case 'CreateWallet': + case "CreateWallet": gradient = WalletGradient.createWallet; break; default: @@ -56,7 +56,7 @@ export default class WalletGradient { case HDSegwitBech32Wallet.type: gradient = WalletGradient.hdSegwitBech32Wallet; break; - case 'CreateWallet': + case "CreateWallet": gradient = WalletGradient.createWallet; break; default: diff --git a/class/watch-only-wallet.js b/class/watch-only-wallet.js index fefce169b36..2459f046a64 100644 --- a/class/watch-only-wallet.js +++ b/class/watch-only-wallet.js @@ -1,12 +1,13 @@ -import { LegacyWallet } from './legacy-wallet'; -import { HDSegwitP2SHWallet } from './hd-segwit-p2sh-wallet'; -import { HDLegacyP2PKHWallet } from './hd-legacy-p2pkh-wallet'; -import { HDSegwitBech32Wallet } from './hd-segwit-bech32-wallet'; -const bitcoin = require('bitcoinjs-lib'); +import { LegacyWallet } from "./legacy-wallet"; +import { HDSegwitP2SHWallet } from "./hd-segwit-p2sh-wallet"; +import { HDLegacyP2PKHWallet } from "./hd-legacy-p2pkh-wallet"; +import { HDSegwitBech32Wallet } from "./hd-segwit-bech32-wallet"; + +const bitcoin = require("bitcoinjs-lib"); export class WatchOnlyWallet extends LegacyWallet { - static type = 'watchOnly'; - static typeReadable = 'Watch-only'; + static type = "watchOnly"; + static typeReadable = "Watch-only"; constructor() { super(); @@ -14,27 +15,40 @@ export class WatchOnlyWallet extends LegacyWallet { } allowSend() { - return !!this.use_with_hardware_wallet && this._hdWalletInstance instanceof HDSegwitBech32Wallet && this._hdWalletInstance.allowSend(); + return ( + !!this.use_with_hardware_wallet && + this._hdWalletInstance instanceof HDSegwitBech32Wallet && + this._hdWalletInstance.allowSend() + ); } allowBatchSend() { return ( - !!this.use_with_hardware_wallet && this._hdWalletInstance instanceof HDSegwitBech32Wallet && this._hdWalletInstance.allowBatchSend() + !!this.use_with_hardware_wallet && + this._hdWalletInstance instanceof HDSegwitBech32Wallet && + this._hdWalletInstance.allowBatchSend() ); } allowSendMax() { return ( - !!this.use_with_hardware_wallet && this._hdWalletInstance instanceof HDSegwitBech32Wallet && this._hdWalletInstance.allowSendMax() + !!this.use_with_hardware_wallet && + this._hdWalletInstance instanceof HDSegwitBech32Wallet && + this._hdWalletInstance.allowSendMax() ); } createTx(utxos, amount, fee, toAddress, memo) { - throw new Error('Not supported'); + throw new Error("Not supported"); } valid() { - if (this.secret.startsWith('xpub') || this.secret.startsWith('ypub') || this.secret.startsWith('zpub')) return true; // xpubs unsupported due to path mixing + if ( + this.secret.startsWith("xpub") || + this.secret.startsWith("ypub") || + this.secret.startsWith("zpub") + ) + return true; // xpubs unsupported due to path mixing try { bitcoin.address.toOutputScript(this.secret); @@ -52,14 +66,17 @@ export class WatchOnlyWallet extends LegacyWallet { */ init() { let hdWalletInstance; - if (this.secret.startsWith('xpub')) hdWalletInstance = new HDLegacyP2PKHWallet(); - else if (this.secret.startsWith('ypub')) hdWalletInstance = new HDSegwitP2SHWallet(); - else if (this.secret.startsWith('zpub')) hdWalletInstance = new HDSegwitBech32Wallet(); + if (this.secret.startsWith("xpub")) + hdWalletInstance = new HDLegacyP2PKHWallet(); + else if (this.secret.startsWith("ypub")) + hdWalletInstance = new HDSegwitP2SHWallet(); + else if (this.secret.startsWith("zpub")) + hdWalletInstance = new HDSegwitBech32Wallet(); else return; hdWalletInstance._xpub = this.secret; if (this._hdWalletInstance) { // now, porting all properties from old object to new one - for (let k of Object.keys(this._hdWalletInstance)) { + for (const k of Object.keys(this._hdWalletInstance)) { hdWalletInstance[k] = this._hdWalletInstance[k]; } hdWalletInstance.generateAddresses(); @@ -76,7 +93,8 @@ export class WatchOnlyWallet extends LegacyWallet { } getAddressForTransaction() { - if (this._hdWalletInstance) return this._hdWalletInstance.getAddressForTransaction(); + if (this._hdWalletInstance) + return this._hdWalletInstance.getAddressForTransaction(); return this.secret; } @@ -91,7 +109,11 @@ export class WatchOnlyWallet extends LegacyWallet { } async fetchBalance() { - if (this.secret.startsWith('xpub') || this.secret.startsWith('ypub') || this.secret.startsWith('zpub')) { + if ( + this.secret.startsWith("xpub") || + this.secret.startsWith("ypub") || + this.secret.startsWith("zpub") + ) { if (!this._hdWalletInstance) this.init(); return this._hdWalletInstance.fetchBalance(); } else { @@ -101,7 +123,11 @@ export class WatchOnlyWallet extends LegacyWallet { } async fetchTransactions() { - if (this.secret.startsWith('xpub') || this.secret.startsWith('ypub') || this.secret.startsWith('zpub')) { + if ( + this.secret.startsWith("xpub") || + this.secret.startsWith("ypub") || + this.secret.startsWith("zpub") + ) { if (!this._hdWalletInstance) this.init(); return this._hdWalletInstance.fetchTransactions(); } else { @@ -112,22 +138,23 @@ export class WatchOnlyWallet extends LegacyWallet { async fetchUtxo() { if (this._hdWalletInstance) return this._hdWalletInstance.fetchUtxo(); - throw new Error('Not initialized'); + throw new Error("Not initialized"); } getUtxo() { if (this._hdWalletInstance) return this._hdWalletInstance.getUtxo(); - throw new Error('Not initialized'); + throw new Error("Not initialized"); } combinePsbt(base64one, base64two) { - if (this._hdWalletInstance) return this._hdWalletInstance.combinePsbt(base64one, base64two); - throw new Error('Not initialized'); + if (this._hdWalletInstance) + return this._hdWalletInstance.combinePsbt(base64one, base64two); + throw new Error("Not initialized"); } broadcastTx(hex) { if (this._hdWalletInstance) return this._hdWalletInstance.broadcastTx(hex); - throw new Error('Not initialized'); + throw new Error("Not initialized"); } /** @@ -137,9 +164,18 @@ export class WatchOnlyWallet extends LegacyWallet { */ createTransaction(utxos, targets, feeRate, changeAddress, sequence) { if (this._hdWalletInstance instanceof HDSegwitBech32Wallet) { - return this._hdWalletInstance.createTransaction(utxos, targets, feeRate, changeAddress, sequence, true); + return this._hdWalletInstance.createTransaction( + utxos, + targets, + feeRate, + changeAddress, + sequence, + true + ); } else { - throw new Error('Not a zpub watch-only wallet, cant create PSBT (or just not initialized)'); + throw new Error( + "Not a zpub watch-only wallet, cant create PSBT (or just not initialized)" + ); } } } diff --git a/currency.js b/currency.js index fb3adb88b13..d5501be2215 100644 --- a/currency.js +++ b/currency.js @@ -1,15 +1,17 @@ -import Frisbee from 'frisbee'; -import AsyncStorage from '@react-native-community/async-storage'; -import { AppStorage } from './class'; -import { FiatUnit } from './models/fiatUnit'; -import DefaultPreference from 'react-native-default-preference'; -import DeviceQuickActions from './class/quickActions'; -let BigNumber = require('bignumber.js'); +import Frisbee from "frisbee"; +import AsyncStorage from "@react-native-community/async-storage"; +import { AppStorage } from "./class"; +import { FiatUnit } from "./models/fiatUnit"; +import DefaultPreference from "react-native-default-preference"; +import DeviceQuickActions from "./class/quickActions"; + +const BigNumber = require("bignumber.js"); + let preferredFiatCurrency = FiatUnit.USD; -let exchangeRates = {}; +const exchangeRates = {}; const STRUCT = { - LAST_UPDATED: 'LAST_UPDATED', + LAST_UPDATED: "LAST_UPDATED" }; /** @@ -20,17 +22,31 @@ const STRUCT = { * @returns {Promise} */ async function setPrefferedCurrency(item) { - await AsyncStorage.setItem(AppStorage.PREFERRED_CURRENCY, JSON.stringify(item)); - await DefaultPreference.setName('group.io.veles.wallet'); - await DefaultPreference.set('preferredCurrency', item.endPointKey); - await DefaultPreference.set('preferredCurrencyLocale', item.locale.replace('-', '_')); + await AsyncStorage.setItem( + AppStorage.PREFERRED_CURRENCY, + JSON.stringify(item) + ); + await DefaultPreference.setName("group.io.veles.wallet"); + await DefaultPreference.set("preferredCurrency", item.endPointKey); + await DefaultPreference.set( + "preferredCurrencyLocale", + item.locale.replace("-", "_") + ); DeviceQuickActions.setQuickActions(); } async function getPreferredCurrency() { - let preferredCurrency = await JSON.parse(await AsyncStorage.getItem(AppStorage.PREFERRED_CURRENCY)); - await DefaultPreference.set('preferredCurrency', preferredCurrency.endPointKey); - await DefaultPreference.set('preferredCurrencyLocale', preferredCurrency.locale.replace('-', '_')); + const preferredCurrency = await JSON.parse( + await AsyncStorage.getItem(AppStorage.PREFERRED_CURRENCY) + ); + await DefaultPreference.set( + "preferredCurrency", + preferredCurrency.endPointKey + ); + await DefaultPreference.set( + "preferredCurrencyLocale", + preferredCurrency.locale.replace("-", "_") + ); return preferredCurrency; } @@ -41,31 +57,50 @@ async function updateExchangeRate() { } try { - preferredFiatCurrency = JSON.parse(await AsyncStorage.getItem(AppStorage.PREFERRED_CURRENCY)); + preferredFiatCurrency = JSON.parse( + await AsyncStorage.getItem(AppStorage.PREFERRED_CURRENCY) + ); } catch (_) {} preferredFiatCurrency = preferredFiatCurrency || FiatUnit.USD; let json; try { const api = new Frisbee({ - baseURI: 'https://api.coindesk.com', + baseURI: "https://api.coindesk.com" }); - let response = await api.get('/v1/bpi/currentprice/' + preferredFiatCurrency.endPointKey + '.json'); + const response = await api.get( + "/v1/bpi/currentprice/" + preferredFiatCurrency.endPointKey + ".json" + ); json = JSON.parse(response.body); - if (!json || !json.bpi || !json.bpi[preferredFiatCurrency.endPointKey] || !json.bpi[preferredFiatCurrency.endPointKey].rate_float) { - throw new Error('Could not update currency rate: ' + response.err); + if ( + !json || + !json.bpi || + !json.bpi[preferredFiatCurrency.endPointKey] || + !json.bpi[preferredFiatCurrency.endPointKey].rate_float + ) { + throw new Error("Could not update currency rate: " + response.err); } } catch (Err) { console.warn(Err); - const lastSavedExchangeRate = JSON.parse(await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES)); - exchangeRates['BTC_' + preferredFiatCurrency.endPointKey] = lastSavedExchangeRate['BTC_' + preferredFiatCurrency.endPointKey] * 1; + const lastSavedExchangeRate = JSON.parse( + await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES) + ); + exchangeRates["BTC_" + preferredFiatCurrency.endPointKey] = + lastSavedExchangeRate["BTC_" + preferredFiatCurrency.endPointKey] * 1; return; } exchangeRates[STRUCT.LAST_UPDATED] = +new Date(); - exchangeRates['BTC_' + preferredFiatCurrency.endPointKey] = json.bpi[preferredFiatCurrency.endPointKey].rate_float * 1; - await AsyncStorage.setItem(AppStorage.EXCHANGE_RATES, JSON.stringify(exchangeRates)); - await AsyncStorage.setItem(AppStorage.PREFERRED_CURRENCY, JSON.stringify(preferredFiatCurrency)); + exchangeRates["BTC_" + preferredFiatCurrency.endPointKey] = + json.bpi[preferredFiatCurrency.endPointKey].rate_float * 1; + await AsyncStorage.setItem( + AppStorage.EXCHANGE_RATES, + JSON.stringify(exchangeRates) + ); + await AsyncStorage.setItem( + AppStorage.PREFERRED_CURRENCY, + JSON.stringify(preferredFiatCurrency) + ); DeviceQuickActions.setQuickActions(); } @@ -81,15 +116,15 @@ async function startUpdater() { } function satoshiToLocalCurrency(satoshi) { - if (!exchangeRates['BTC_' + preferredFiatCurrency.endPointKey]) { + if (!exchangeRates["BTC_" + preferredFiatCurrency.endPointKey]) { startUpdater(); - return '...'; + return "..."; } let b = new BigNumber(satoshi); b = b .dividedBy(100000000) - .multipliedBy(exchangeRates['BTC_' + preferredFiatCurrency.endPointKey]) + .multipliedBy(exchangeRates["BTC_" + preferredFiatCurrency.endPointKey]) .toString(10); b = parseFloat(b).toFixed(2); @@ -97,17 +132,17 @@ function satoshiToLocalCurrency(satoshi) { try { formatter = new Intl.NumberFormat(preferredFiatCurrency.locale, { - style: 'currency', + style: "currency", currency: preferredFiatCurrency.endPointKey, - minimumFractionDigits: 2, + minimumFractionDigits: 2 }); } catch (error) { console.warn(error); console.log(error); formatter = new Intl.NumberFormat(FiatUnit.USD.locale, { - style: 'currency', + style: "currency", currency: preferredFiatCurrency.endPointKey, - minimumFractionDigits: 2, + minimumFractionDigits: 2 }); } diff --git a/encryption.js b/encryption.js index 1a0df246240..82689d21443 100644 --- a/encryption.js +++ b/encryption.js @@ -1,12 +1,12 @@ -let CryptoJS = require('crypto-js'); +const CryptoJS = require("crypto-js"); module.exports.encrypt = function(data, password) { - let ciphertext = CryptoJS.AES.encrypt(data, password); + const ciphertext = CryptoJS.AES.encrypt(data, password); return ciphertext.toString(); }; module.exports.decrypt = function(data, password) { - let bytes = CryptoJS.AES.decrypt(data, password); + const bytes = CryptoJS.AES.decrypt(data, password); let str = false; try { str = bytes.toString(CryptoJS.enc.Utf8); diff --git a/events.js b/events.js index 92f46a9ef03..c37a7c384ef 100644 --- a/events.js +++ b/events.js @@ -1,23 +1,28 @@ function EV(eventName, arg, isExclusive) { if (Object.values(EV.enum).indexOf(eventName) === -1) { - return console.warn('Unregistered event', eventName, 'registered events:', EV.enum); + return console.warn( + "Unregistered event", + eventName, + "registered events:", + EV.enum + ); } EV.callbacks = EV.callbacks || {}; // static variable EV.callbacks[eventName] = EV.callbacks[eventName] || []; - if (typeof arg !== 'function') { + if (typeof arg !== "function") { // then its an argument - console.log('got event', eventName, '...'); - for (let cc of EV.callbacks[eventName]) { - console.log('dispatching event', eventName); + console.log("got event", eventName, "..."); + for (const cc of EV.callbacks[eventName]) { + console.log("dispatching event", eventName); cc(arg); } } else { // its a callback. subscribe it to event - console.log('someone subscribed to', eventName); + console.log("someone subscribed to", eventName); if (isExclusive) { // if it'a an excluside subscribe - other subscribers should be terminated - console.log('exclusive subscribe'); + console.log("exclusive subscribe"); EV.callbacks[eventName] = []; } EV.callbacks[eventName].push(arg); @@ -26,15 +31,15 @@ function EV(eventName, arg, isExclusive) { EV.enum = { // emitted when local wallet created or deleted, so one must redraw wallets carousel - WALLETS_COUNT_CHANGED: 'WALLETS_COUNT_CHANGED', + WALLETS_COUNT_CHANGED: "WALLETS_COUNT_CHANGED", // emitted when local wallet (usually current wallet) has changed number of transactions // so one must redraw main screen transactions list and WalletTransactions screen tx list - TRANSACTIONS_COUNT_CHANGED: 'TRANSACTIONS_COUNT_CHANGED', + TRANSACTIONS_COUNT_CHANGED: "TRANSACTIONS_COUNT_CHANGED", // emitted when we know for sure that on remote server tx list // changed (usually for current wallet) - REMOTE_TRANSACTIONS_COUNT_CHANGED: 'REMOTE_TRANSACTIONS_COUNT_CHANGED', + REMOTE_TRANSACTIONS_COUNT_CHANGED: "REMOTE_TRANSACTIONS_COUNT_CHANGED" // RECEIVE_ADDRESS_CHANGED: 'RECEIVE_ADDRESS_CHANGED', }; diff --git a/index.js b/index.js index 5e581df6e47..f617102b456 100644 --- a/index.js +++ b/index.js @@ -1,15 +1,15 @@ -import 'intl'; -import 'intl/locale-data/jsonp/en'; -import React from 'react'; -import './shim.js'; -import { AppRegistry } from 'react-native'; -import WalletMigrate from './screen/wallets/walletMigrate'; -import { name as appName } from './app.json'; -import App from './App'; -import LottieView from 'lottie-react-native'; -import UnlockWith from './UnlockWith.js'; +import "intl"; +import "intl/locale-data/jsonp/en"; +import React from "react"; +import "./shim.js"; +import { AppRegistry } from "react-native"; +import WalletMigrate from "./screen/wallets/walletMigrate"; +import { name as appName } from "./app.json"; +import App from "./App"; +import LottieView from "lottie-react-native"; +import UnlockWith from "./UnlockWith.js"; -const A = require('./analytics'); +const A = require("./analytics"); if (!Error.captureStackTrace) { // captureStackTrace is only available when debugging @@ -19,7 +19,11 @@ if (!Error.captureStackTrace) { class BlueAppComponent extends React.Component { constructor(props) { super(props); - this.state = { isMigratingData: true, onAnimationFinished: false, successfullyAuthenticated: false }; + this.state = { + isMigratingData: true, + onAnimationFinished: false, + successfullyAuthenticated: false + }; } componentDidMount() { @@ -50,8 +54,8 @@ class BlueAppComponent extends React.Component { (this.loadingSplash = ref)} onAnimationFinish={this.onAnimationFinish} - source={require('./img/splash.json')} - style={{ backgroundColor: '#383737' }} + source={require("./img/splash.json")} + style={{ backgroundColor: "#383737" }} autoPlay loop={false} /> @@ -61,15 +65,17 @@ class BlueAppComponent extends React.Component { return this.state.successfullyAuthenticated ? ( ) : ( - + ); } else { return ( (this.loadingSplash = ref)} onAnimationFinish={this.onAnimationFinish} - source={require('./img/splash.json')} - style={{ backgroundColor: '#383737' }} + source={require("./img/splash.json")} + style={{ backgroundColor: "#383737" }} autoPlay loop={false} /> diff --git a/loc/ZAR_Afr.js b/loc/ZAR_Afr.js index 222208860cd..5f445404333 100644 --- a/loc/ZAR_Afr.js +++ b/loc/ZAR_Afr.js @@ -1,236 +1,245 @@ module.exports = { _: { - storage_is_encrypted: 'U geheue spasie is nou ge-enkripteer. ‘n Wagwoord word benodig om toegang te verkry. ', - enter_password: 'Sleutel wagwoord in', - bad_password: 'Verkeerde wagwoord, probeer weer', - never: 'nooit', - continue: 'Gaan voort', - ok: 'OK', + storage_is_encrypted: + "U geheue spasie is nou ge-enkripteer. ‘n Wagwoord word benodig om toegang te verkry. ", + enter_password: "Sleutel wagwoord in", + bad_password: "Verkeerde wagwoord, probeer weer", + never: "nooit", + continue: "Gaan voort", + ok: "OK" }, wallets: { - select_wallet: 'Kies Beursie', - options: 'opsies', + select_wallet: "Kies Beursie", + options: "opsies", createBitcoinWallet: - 'U het nie huidiglik `n geldige Bitcoin Beursie nie. Skep of voer eers ‘n Bitcoin Beursie in, sodat ‘n Bitcoin Lightning Beursie geskep en bevonds mag word. Wil U voortgaan?', + "U het nie huidiglik `n geldige Bitcoin Beursie nie. Skep of voer eers ‘n Bitcoin Beursie in, sodat ‘n Bitcoin Lightning Beursie geskep en bevonds mag word. Wil U voortgaan?", list: { - app_name: 'Veles Wallet', - title: 'beursies', + app_name: "Veles Wallet", + title: "beursies", header: - 'U beursie verteenwoordig ‘n sleutelkombinasie, bestaande uit geheims (privaat sleutel) en address' + - 'wat u kan gebruik om fondse te ontvang.', - add: 'Skep Beursie', - create_a_wallet: 'Skep ‘n beursie', - create_a_wallet1: 'Dit is gratis so skep', - create_a_wallet2: 'soveel as wat u benodig', - latest_transaction: 'laaste transaksie', - empty_txs1: 'U transaksies is hier beskikbaar,', - empty_txs2: 'huidiglik geen transaksies', - tap_here_to_buy: 'Raak hier om Bitcoin te koop', + "U beursie verteenwoordig ‘n sleutelkombinasie, bestaande uit geheims (privaat sleutel) en address" + + "wat u kan gebruik om fondse te ontvang.", + add: "Skep Beursie", + create_a_wallet: "Skep ‘n beursie", + create_a_wallet1: "Dit is gratis so skep", + create_a_wallet2: "soveel as wat u benodig", + latest_transaction: "laaste transaksie", + empty_txs1: "U transaksies is hier beskikbaar,", + empty_txs2: "huidiglik geen transaksies", + tap_here_to_buy: "Raak hier om Bitcoin te koop" }, reorder: { - title: 'Herorganiseer Beursies', + title: "Herorganiseer Beursies" }, add: { - title: 'skep beursie', + title: "skep beursie", description: - 'U kan ‘n beursie invoer (in WIF - Wallet Import Format), of ‘n nuwe beursie skep. Beursies ondersteun Segwit as standaard.', - scan: 'Skandeer', - create: 'Skep', - label_new_segwit: 'Nuwe SegWit', - label_new_lightning: 'Nuwe Lightning', - wallet_name: 'beursie naam', - wallet_type: 'tipe', - or: 'of', - import_wallet: 'Beursie Invoer', - imported: 'Ingevoer', - coming_soon: 'In die toekoms', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "U kan ‘n beursie invoer (in WIF - Wallet Import Format), of ‘n nuwe beursie skep. Beursies ondersteun Segwit as standaard.", + scan: "Skandeer", + create: "Skep", + label_new_segwit: "Nuwe SegWit", + label_new_lightning: "Nuwe Lightning", + wallet_name: "beursie naam", + wallet_type: "tipe", + or: "of", + import_wallet: "Beursie Invoer", + imported: "Ingevoer", + coming_soon: "In die toekoms", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Beursiet', - address: 'AdresAddress', - type: 'Tipe', - label: 'Etiket', - destination: 'bestemming', - description: 'beskrywing', - are_you_sure: 'Is u Seker?', - yes_delete: 'Ja, vernietig', - no_cancel: 'Nee, kanseleerl', - delete: 'Vernietig', - save: 'Berg', - delete_this_wallet: 'Vernietig hierdie beursie', - export_backup: 'voer uit / kopieer', - buy_bitcoin: 'Koop Bitcoin', - show_xpub: 'Wys beursie XPUB', + title: "Beursiet", + address: "AdresAddress", + type: "Tipe", + label: "Etiket", + destination: "bestemming", + description: "beskrywing", + are_you_sure: "Is u Seker?", + yes_delete: "Ja, vernietig", + no_cancel: "Nee, kanseleerl", + delete: "Vernietig", + save: "Berg", + delete_this_wallet: "Vernietig hierdie beursie", + export_backup: "voer uit / kopieer", + buy_bitcoin: "Koop Bitcoin", + show_xpub: "Wys beursie XPUB" }, export: { - title: 'beursie uitvoer', + title: "beursie uitvoer" }, xpub: { - title: 'beursie XPUB', - copiedToClipboard: 'Gestuur na klipbord.', + title: "beursie XPUB", + copiedToClipboard: "Gestuur na klipbord." }, import: { - title: 'Invoer', + title: "Invoer", explanation: - 'Sleutel mnemonic, privaat sleutel, WIF, of enige text verwysing. Veles Wallet sal die korrekte formaat kies en u beursie importeer ', - imported: 'Invoer suksesvol', - error: 'U invoer het misluk. Maak asseblief seker u data is korrek en geldig.', - success: 'Suksesvol', - do_import: 'Invoer', - scan_qr: 'of skandeer QR kode?', + "Sleutel mnemonic, privaat sleutel, WIF, of enige text verwysing. Veles Wallet sal die korrekte formaat kies en u beursie importeer ", + imported: "Invoer suksesvol", + error: + "U invoer het misluk. Maak asseblief seker u data is korrek en geldig.", + success: "Suksesvol", + do_import: "Invoer", + scan_qr: "of skandeer QR kode?" }, scanQrWif: { - go_back: 'Gaan Terug', - cancel: 'Kanseleer', - decoding: 'Decoding', - input_password: 'Input password', - password_explain: 'Hierdie is ‘n BIP38 ge-enkripteerde privaat sleutel', - bad_password: 'Wagwoord verkeerd', - wallet_already_exists: 'Hierdie beursie bestaan alreeds', - bad_wif: 'WIF verkeerd', - imported_wif: 'WIF invoer suksesvol ', - with_address: ' met adres ', - imported_segwit: 'Segwit Invoer Suksesvol', - imported_legacy: 'Legacy Invoer', - imported_watchonly: 'Kyk Slegs invoer suksesvol', - }, + go_back: "Gaan Terug", + cancel: "Kanseleer", + decoding: "Decoding", + input_password: "Input password", + password_explain: "Hierdie is ‘n BIP38 ge-enkripteerde privaat sleutel", + bad_password: "Wagwoord verkeerd", + wallet_already_exists: "Hierdie beursie bestaan alreeds", + bad_wif: "WIF verkeerd", + imported_wif: "WIF invoer suksesvol ", + with_address: " met adres ", + imported_segwit: "Segwit Invoer Suksesvol", + imported_legacy: "Legacy Invoer", + imported_watchonly: "Kyk Slegs invoer suksesvol" + } }, transactions: { list: { - tabBarLabel: 'Transaksies', - title: 'transaksies', - description: 'Lys met inkomende en uitgaande transaksies van u beursies', - conf: 'bev.', + tabBarLabel: "Transaksies", + title: "transaksies", + description: "Lys met inkomende en uitgaande transaksies van u beursies", + conf: "bev." }, details: { - title: 'Transaksie', - from: 'Inset', - to: 'Resultaat', - copy: 'Kopieer', - transaction_details: 'Transaksie besonderhede', - show_in_block_explorer: 'Wys in blok verkenner', - }, + title: "Transaksie", + from: "Inset", + to: "Resultaat", + copy: "Kopieer", + transaction_details: "Transaksie besonderhede", + show_in_block_explorer: "Wys in blok verkenner" + } }, send: { - header: 'Stuur', + header: "Stuur", details: { - title: 'skep transaksie', - amount_field_is_not_valid: 'Bedrag is ongeldig', - fee_field_is_not_valid: 'Fooi spasie is ongeldig', - address_field_is_not_valid: 'Adres is ongeldig', - total_exceeds_balance: 'Die bedrag is meer as die beskikbare balans.', - create_tx_error: 'Daar was ‘n probleem met die skepping van die transaksie. Bevestig asseblief die adres is geldig.', - address: 'adres', - amount_placeholder: 'bedrag om te stuur (in VLS)', - fee_placeholder: 'plus transaksie fooi (in VLS)', - note_placeholder: 'persoonlike notas', - cancel: 'Kanselleer', - scan: 'Skandeer', - send: 'Stuur', - create: 'Skep', - remaining_balance: 'Oorblywende balans', + title: "skep transaksie", + amount_field_is_not_valid: "Bedrag is ongeldig", + fee_field_is_not_valid: "Fooi spasie is ongeldig", + address_field_is_not_valid: "Adres is ongeldig", + total_exceeds_balance: "Die bedrag is meer as die beskikbare balans.", + create_tx_error: + "Daar was ‘n probleem met die skepping van die transaksie. Bevestig asseblief die adres is geldig.", + address: "adres", + amount_placeholder: "bedrag om te stuur (in VLS)", + fee_placeholder: "plus transaksie fooi (in VLS)", + note_placeholder: "persoonlike notas", + cancel: "Kanselleer", + scan: "Skandeer", + send: "Stuur", + create: "Skep", + remaining_balance: "Oorblywende balans" }, confirm: { - header: 'Bevestig', - sendNow: 'Stuur nou', + header: "Bevestig", + sendNow: "Stuur nou" }, success: { - done: 'Klaar', + done: "Klaar" }, create: { - details: 'Besonderhede', - title: 'skep transaksie', - error: 'Daar is ‘n probleem met die transaksie. Ongeldige adres of bedrag?', - go_back: 'Gaan Terug', - this_is_hex: 'Hierdie is die transaksie hex, geteken en gereed om na die netwerk uitgesaai te word.', - to: 'Aan', - amount: 'Bedrag', - fee: 'Fooi', - tx_size: 'TX groote', - satoshi_per_byte: 'Satoshi per byte', - memo: 'Memo', - broadcast: 'Saai uit', - not_enough_fee: 'Fooi te laag. Vermeerder die fooi', - }, + details: "Besonderhede", + title: "skep transaksie", + error: + "Daar is ‘n probleem met die transaksie. Ongeldige adres of bedrag?", + go_back: "Gaan Terug", + this_is_hex: + "Hierdie is die transaksie hex, geteken en gereed om na die netwerk uitgesaai te word.", + to: "Aan", + amount: "Bedrag", + fee: "Fooi", + tx_size: "TX groote", + satoshi_per_byte: "Satoshi per byte", + memo: "Memo", + broadcast: "Saai uit", + not_enough_fee: "Fooi te laag. Vermeerder die fooi" + } }, receive: { - header: 'Ontvang', + header: "Ontvang", details: { - title: 'Deel adres met krediteur', - share: 'deel', - copiedToClipboard: 'Gekopieer na klipbord.', - label: 'Beskrywing', - create: 'Skep', - setAmount: 'Bedrag ontvang', - }, + title: "Deel adres met krediteur", + share: "deel", + copiedToClipboard: "Gekopieer na klipbord.", + label: "Beskrywing", + create: "Skep", + setAmount: "Bedrag ontvang" + } }, buyBitcoin: { - header: 'Koop Bitcoin', - tap_your_address: 'Raak aan die adres om dit na die klipbord the stuur:', - copied: 'Gekopieer na klipbord!', + header: "Koop Bitcoin", + tap_your_address: "Raak aan die adres om dit na die klipbord the stuur:", + copied: "Gekopieer na klipbord!" }, settings: { - header: 'instellings', - plausible_deniability: 'Geloofwaardige ontkenbaarheid...', - storage_not_encrypted: 'Berging: Nie-geenkripteer nie', - storage_encrypted: 'Berging: Ge-enkripteer', - password: 'Wagwoord', - password_explain: 'Skep die wagwoord wat u sal gebruik om u berging te de-enkripteer', - retype_password: 'Hervoer wagwoord', - passwords_do_not_match: 'Wagwoorde stem nie oor een nie', - encrypt_storage: 'Enkripteer Berging', - lightning_settings: 'Lightning Instellings', + header: "instellings", + plausible_deniability: "Geloofwaardige ontkenbaarheid...", + storage_not_encrypted: "Berging: Nie-geenkripteer nie", + storage_encrypted: "Berging: Ge-enkripteer", + password: "Wagwoord", + password_explain: + "Skep die wagwoord wat u sal gebruik om u berging te de-enkripteer", + retype_password: "Hervoer wagwoord", + passwords_do_not_match: "Wagwoorde stem nie oor een nie", + encrypt_storage: "Enkripteer Berging", + lightning_settings: "Lightning Instellings", lightning_settings_explain: - 'Om u eie LND node te konnekteer, installeer asseblief LndHub' + - ' and put its URL here in settings. Leave blank om die standaard LndHub' + - '(lndhub.io) te gebruik', - save: 'stoor', - about: 'info', - language: 'Taal', - currency: 'Geldeenheid', + "Om u eie LND node te konnekteer, installeer asseblief LndHub" + + " and put its URL here in settings. Leave blank om die standaard LndHub" + + "(lndhub.io) te gebruik", + save: "stoor", + about: "info", + language: "Taal", + currency: "Geldeenheid" }, plausibledeniability: { - title: 'Geloofwaardige Ontkenbaarheid', + title: "Geloofwaardige Ontkenbaarheid", help: - 'Onder sekere omstandighede mag u dalk geforseer word om u ' + - 'wagwoord te deel teen u wil. Om u te beskerm kan Veles Wallet ‘n ' + - 'tweede “fantasie” beursie skep wat as skerm kan dien. Indien u ' + - 'hierdie wagwoord deel sal die 3de party nie toegang tot u hoof fondse kry nie.', - help2: 'Fantasie berging is heeltemal funksioneel', - create_fake_storage: 'Skep fantasie berging wagwoord', - go_back: 'Gaan terug', - create_password: 'Skep ‘n wagwoord', - create_password_explanation: 'Die wagwoord vir fantasie berging moet verskil van die wagwoord vir hoof berging', - password_should_not_match: 'Die wagwoord vir fantasie berging moet verskil van die wagwoord vir hoof berging.', - retype_password: 'Hervoer wagwoord', - passwords_do_not_match: 'Wagwoorde vergelyk nie, probeer weer', - success: 'Sukses', + "Onder sekere omstandighede mag u dalk geforseer word om u " + + "wagwoord te deel teen u wil. Om u te beskerm kan Veles Wallet ‘n " + + "tweede “fantasie” beursie skep wat as skerm kan dien. Indien u " + + "hierdie wagwoord deel sal die 3de party nie toegang tot u hoof fondse kry nie.", + help2: "Fantasie berging is heeltemal funksioneel", + create_fake_storage: "Skep fantasie berging wagwoord", + go_back: "Gaan terug", + create_password: "Skep ‘n wagwoord", + create_password_explanation: + "Die wagwoord vir fantasie berging moet verskil van die wagwoord vir hoof berging", + password_should_not_match: + "Die wagwoord vir fantasie berging moet verskil van die wagwoord vir hoof berging.", + retype_password: "Hervoer wagwoord", + passwords_do_not_match: "Wagwoorde vergelyk nie, probeer weer", + success: "Sukses" }, lnd: { - title: 'bestuur fondse', - choose_source_wallet: 'Kies ‘n bron beursie', - refill_lnd_balance: 'Herlaai Lightning beursie', - refill: 'Herlaai', - withdraw: 'Ontrek', - expired: 'Verval', - placeholder: 'Faktuur', - sameWalletAsInvoiceError: 'U kan nie ‘n faktuur betaal met die selfde beursie waarmee die faktuur geksep is nie.', + title: "bestuur fondse", + choose_source_wallet: "Kies ‘n bron beursie", + refill_lnd_balance: "Herlaai Lightning beursie", + refill: "Herlaai", + withdraw: "Ontrek", + expired: "Verval", + placeholder: "Faktuur", + sameWalletAsInvoiceError: + "U kan nie ‘n faktuur betaal met die selfde beursie waarmee die faktuur geksep is nie." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/ZAR_Xho.js b/loc/ZAR_Xho.js index cb1d4762ef4..90c5f008055 100644 --- a/loc/ZAR_Xho.js +++ b/loc/ZAR_Xho.js @@ -1,239 +1,247 @@ module.exports = { _: { - storage_is_encrypted: 'Ukugcinwa kwakho kubhaliwe. Inombolo yokuvula iyadingeka ukuba ichithwe', - enter_password: 'Faka inombolo yokuvula', - bad_password: 'Iphasiwedi engalunganga, zama kwakhona', - never: 'Ungalingi', - continue: 'Qhubeka', - ok: 'OK', + storage_is_encrypted: + "Ukugcinwa kwakho kubhaliwe. Inombolo yokuvula iyadingeka ukuba ichithwe", + enter_password: "Faka inombolo yokuvula", + bad_password: "Iphasiwedi engalunganga, zama kwakhona", + never: "Ungalingi", + continue: "Qhubeka", + ok: "OK" }, wallets: { - select_wallet: 'Khetha ingxowa', - options: 'Ukhetho', + select_wallet: "Khetha ingxowa", + options: "Ukhetho", createBitcoinWallet: - 'Okwangoku awunayo ingxowa yebitcoin. Ukuze kuxhaswe ingxowa ekhawulezayo, Ingxowa yeBitcoin kufuneka idalwe okanye ikhutshelwe. Ungathanda ukuqhubeka ?', + "Okwangoku awunayo ingxowa yebitcoin. Ukuze kuxhaswe ingxowa ekhawulezayo, Ingxowa yeBitcoin kufuneka idalwe okanye ikhutshelwe. Ungathanda ukuqhubeka ?", list: { - app_name: 'Veles Wallet', - title: 'Ingxowa', - header: 'Ingxowa imele ukuba nemfihlelo yokuyivula nekheli kwaye unokuyisebenzisa ukwamkela imali.', - add: 'Yongeza Ingxowa', - create_a_wallet: 'Yenza ingxowa', - create_a_wallet1: 'Ayihlawulelwa kwaye ungayenza', - create_a_wallet2: 'Ungenza zibeninzi indlela zokuhlawula', - latest_transaction: 'Utshintsho olutsha', - empty_txs1: 'Intengiso yakho iya kubonakala apha,', - empty_txs2: 'akuho nanye okwangoku', - tap_here_to_buy: 'Cofa apha ukuthenga ibitcoin', + app_name: "Veles Wallet", + title: "Ingxowa", + header: + "Ingxowa imele ukuba nemfihlelo yokuyivula nekheli kwaye unokuyisebenzisa ukwamkela imali.", + add: "Yongeza Ingxowa", + create_a_wallet: "Yenza ingxowa", + create_a_wallet1: "Ayihlawulelwa kwaye ungayenza", + create_a_wallet2: "Ungenza zibeninzi indlela zokuhlawula", + latest_transaction: "Utshintsho olutsha", + empty_txs1: "Intengiso yakho iya kubonakala apha,", + empty_txs2: "akuho nanye okwangoku", + tap_here_to_buy: "Cofa apha ukuthenga ibitcoin" }, reorder: { - title: 'Yenza kwakhona ingxowa', + title: "Yenza kwakhona ingxowa" }, add: { - title: 'yongeza ingxowa', + title: "yongeza ingxowa", description: - 'Unokukhangela ingxowa yephepha yokugcinwa kwephepha ( kwi-WIF – indlela lokungenisa ingxowa), okanye wenze ingxowa entsha. Ingxowa yeSegwit exhaswa yi-default.', - scan: 'Ukuqondisa', - create: 'Yakha', - label_new_segwit: 'SegWit entsha', - label_new_lightning: 'Umbane omtsha', - wallet_name: 'igama lengxowa', - wallet_type: 'uhlobo', - or: 'okanye', - import_wallet: 'Ukungenisa ingxowa', - imported: 'ngeniswa', - coming_soon: 'Kuza ngokukhawuleza', - lightning: 'Umbane', - bitcoin: 'Bitcoin', + "Unokukhangela ingxowa yephepha yokugcinwa kwephepha ( kwi-WIF – indlela lokungenisa ingxowa), okanye wenze ingxowa entsha. Ingxowa yeSegwit exhaswa yi-default.", + scan: "Ukuqondisa", + create: "Yakha", + label_new_segwit: "SegWit entsha", + label_new_lightning: "Umbane omtsha", + wallet_name: "igama lengxowa", + wallet_type: "uhlobo", + or: "okanye", + import_wallet: "Ukungenisa ingxowa", + imported: "ngeniswa", + coming_soon: "Kuza ngokukhawuleza", + lightning: "Umbane", + bitcoin: "Bitcoin" }, details: { - title: 'Ingxowa', - address: 'Ikheli', - type: 'Uhlobo', - label: 'Igama', - destination: 'ukuya kuyo', - description: 'ukuya kuyo', - are_you_sure: 'Ingaba uqinisekile?', - yes_delete: 'Ewe, yisuse', - no_cancel: 'Hayi, rhoxisa', - delete: 'Cima', - save: 'Gcina', - delete_this_wallet: 'Cima le ngxowa', - export_backup: 'Ukuthumela ngaphandle / yokugcina', - buy_bitcoin: 'Thenga ibitcoin', - show_xpub: 'Bonise ingxowa XPUB', + title: "Ingxowa", + address: "Ikheli", + type: "Uhlobo", + label: "Igama", + destination: "ukuya kuyo", + description: "ukuya kuyo", + are_you_sure: "Ingaba uqinisekile?", + yes_delete: "Ewe, yisuse", + no_cancel: "Hayi, rhoxisa", + delete: "Cima", + save: "Gcina", + delete_this_wallet: "Cima le ngxowa", + export_backup: "Ukuthumela ngaphandle / yokugcina", + buy_bitcoin: "Thenga ibitcoin", + show_xpub: "Bonise ingxowa XPUB" }, export: { - title: 'ukuthunyelwa kweebhanki ', + title: "ukuthunyelwa kweebhanki " }, xpub: { - title: 'ingxowa XPUB', - copiedToClipboard: 'Ikopishwe kwi-clipboard', + title: "ingxowa XPUB", + copiedToClipboard: "Ikopishwe kwi-clipboard" }, import: { - title: 'ukungenisa', + title: "ukungenisa", explanation: - 'Bhale apha imnemonic yakho, ngundoqo, WIF , okanye nantoni na onayo. Veles Wallet uya kwenza konke okusemandleni ukuqiqa ifomathi efanelekileyo kwaye ingenise ingxowa yakho', - imported: 'Ngenisiwe', - error: 'Ayiphumelelanga ukungenisa. Nceda, uqiniseka ukuba idata ehlinzekiweyo iyasebenza.', - success: 'Iphumelele', - do_import: 'Ngeniswe', - scan_qr: 'okanye ukukhangela iQR code?', + "Bhale apha imnemonic yakho, ngundoqo, WIF , okanye nantoni na onayo. Veles Wallet uya kwenza konke okusemandleni ukuqiqa ifomathi efanelekileyo kwaye ingenise ingxowa yakho", + imported: "Ngenisiwe", + error: + "Ayiphumelelanga ukungenisa. Nceda, uqiniseka ukuba idata ehlinzekiweyo iyasebenza.", + success: "Iphumelele", + do_import: "Ngeniswe", + scan_qr: "okanye ukukhangela iQR code?" }, scanQrWif: { - go_back: 'Buya Umva', - cancel: 'Rhoxisa', - decoding: 'Ukumisela', - input_password: 'Igama lokungena', - password_explain: 'Yi le BIP38 ikhifidi yangasese itsixe', - bad_password: 'Inombolo yokuvula eli ngalunganga ', - wallet_already_exists: 'Ikhredithi enjalo sele ikhona', - bad_wif: 'Ezimbi WIF', - imported_wif: 'Ngeniswa WIF ', - with_address: ' Nge dilesi ', - imported_segwit: 'Ngeniswa SegWit', - imported_legacy: 'Ngeniswa ilifa', - imported_watchonly: 'Ngeniswa bukele-kuphela', - }, + go_back: "Buya Umva", + cancel: "Rhoxisa", + decoding: "Ukumisela", + input_password: "Igama lokungena", + password_explain: "Yi le BIP38 ikhifidi yangasese itsixe", + bad_password: "Inombolo yokuvula eli ngalunganga ", + wallet_already_exists: "Ikhredithi enjalo sele ikhona", + bad_wif: "Ezimbi WIF", + imported_wif: "Ngeniswa WIF ", + with_address: " Nge dilesi ", + imported_segwit: "Ngeniswa SegWit", + imported_legacy: "Ngeniswa ilifa", + imported_watchonly: "Ngeniswa bukele-kuphela" + } }, transactions: { list: { - tabBarLabel: 'Ngeniswa', - title: 'ngeniswa', - description: 'Uluhlu lokungena okanye ukuphuma kweekhredithi zakho', - conf: 'conf', + tabBarLabel: "Ngeniswa", + title: "ngeniswa", + description: "Uluhlu lokungena okanye ukuphuma kweekhredithi zakho", + conf: "conf" }, details: { - title: 'Ngeniswa', - from: 'Negalelo', - to: 'Mveliso', - copy: 'Ikopi', - transaction_details: 'Iinkcukacha zentengiselwano', - show_in_block_explorer: 'Bonisa ibhloko umhloi', - }, + title: "Ngeniswa", + from: "Negalelo", + to: "Mveliso", + copy: "Ikopi", + transaction_details: "Iinkcukacha zentengiselwano", + show_in_block_explorer: "Bonisa ibhloko umhloi" + } }, send: { - header: 'Thumela', + header: "Thumela", details: { - title: 'ukudala ukuthenga', - amount_field_is_not_valid: 'intsimi yexabiso ayivumelekanga', - fee_field_is_not_valid: 'Intsimi yentlawulo ayivumelekanga ', - address_field_is_not_valid: 'Intsimi yeedilesi ayivumelekanga', - total_exceeds_balance: 'Imali yokuthumela idlula imali ekhoyo.', - create_tx_error: 'Kukho impazamo yokudala ukuthengiselana. Nceda, qinisekisa ukuba idilesi iyasebenza.', - address: 'idilesi', - amount_placeholder: 'inani lokuthumela (nge VLS)', - fee_placeholder: 'kunye nentlawulo yokuthengiswa (nge VLS)', - note_placeholder: 'inqaku kumntu', - cancel: 'Rhoxisa', - scan: 'Ukutshekisha', - send: 'Thumela', - create: 'Yenza', - remaining_balance: 'Ibhalansi eseleyo', + title: "ukudala ukuthenga", + amount_field_is_not_valid: "intsimi yexabiso ayivumelekanga", + fee_field_is_not_valid: "Intsimi yentlawulo ayivumelekanga ", + address_field_is_not_valid: "Intsimi yeedilesi ayivumelekanga", + total_exceeds_balance: "Imali yokuthumela idlula imali ekhoyo.", + create_tx_error: + "Kukho impazamo yokudala ukuthengiselana. Nceda, qinisekisa ukuba idilesi iyasebenza.", + address: "idilesi", + amount_placeholder: "inani lokuthumela (nge VLS)", + fee_placeholder: "kunye nentlawulo yokuthengiswa (nge VLS)", + note_placeholder: "inqaku kumntu", + cancel: "Rhoxisa", + scan: "Ukutshekisha", + send: "Thumela", + create: "Yenza", + remaining_balance: "Ibhalansi eseleyo" }, confirm: { - header: 'Qiniseka', - sendNow: 'Thumela ngoku', + header: "Qiniseka", + sendNow: "Thumela ngoku" }, success: { - done: 'Kwenzekile', + done: "Kwenzekile" }, create: { - details: 'Iinkcukacha', - title: 'ukudala ukuthenga', - error: 'Impazamo yokudala ukuthengiselana. Idilesi engavumelekanga okanye imali yokuthumela?', - go_back: 'Buya umva', - this_is_hex: 'Le yi ntengo hex, ityikityiwe ilungele ukukhutshelwa kumnatha.', - to: 'Iya ku', - amount: 'Isixa', - fee: 'Ntlawulo', - tx_size: 'TX ubungakanani', - satoshi_per_byte: 'Satoshi nge-byte', - memo: 'Memo', - broadcast: 'Sasazwa', - not_enough_fee: 'Akukho mali e neleyo. UKwandisa intlawulo ', - }, + details: "Iinkcukacha", + title: "ukudala ukuthenga", + error: + "Impazamo yokudala ukuthengiselana. Idilesi engavumelekanga okanye imali yokuthumela?", + go_back: "Buya umva", + this_is_hex: + "Le yi ntengo hex, ityikityiwe ilungele ukukhutshelwa kumnatha.", + to: "Iya ku", + amount: "Isixa", + fee: "Ntlawulo", + tx_size: "TX ubungakanani", + satoshi_per_byte: "Satoshi nge-byte", + memo: "Memo", + broadcast: "Sasazwa", + not_enough_fee: "Akukho mali e neleyo. UKwandisa intlawulo " + } }, receive: { - header: 'Fumana', + header: "Fumana", details: { - title: 'Wabelane ngale dilesi nomhlawuli', - share: 'yabelana', - copiedToClipboard: 'Ikhutshelwe kwi-clipboard', - label: 'Inkcazo', - create: 'Yenza', - setAmount: 'Fumana ngexabiso', - }, + title: "Wabelane ngale dilesi nomhlawuli", + share: "yabelana", + copiedToClipboard: "Ikhutshelwe kwi-clipboard", + label: "Inkcazo", + create: "Yenza", + setAmount: "Fumana ngexabiso" + } }, buyBitcoin: { - header: 'Thenga Ibitcoin', - tap_your_address: 'Thepha idilesi yakho ukuyikopisha kwi-clipboard:', - copied: 'Ikhutshelwe kwi-clipboard!', + header: "Thenga Ibitcoin", + tap_your_address: "Thepha idilesi yakho ukuyikopisha kwi-clipboard:", + copied: "Ikhutshelwe kwi-clipboard!" }, settings: { - header: 'Izicwangciso', - plausible_deniability: 'Ukuphika...', - storage_not_encrypted: 'Ukugciwa: hayi ngekhodi', - storage_encrypted: 'Ukugciwa: ngekhodi', - password: 'Inombolo yokuvula', - password_explain: 'Ukudala iinombolo yokuvula oyisebenzisayo ukucima ukugcina', - retype_password: 'Phina inombolo yokuvula', - passwords_do_not_match: 'Inombolo yokuvula azifani', - encrypt_storage: 'Kubhala u kubhala', - lightning_settings: 'Izixhobo zokukhanyisa', + header: "Izicwangciso", + plausible_deniability: "Ukuphika...", + storage_not_encrypted: "Ukugciwa: hayi ngekhodi", + storage_encrypted: "Ukugciwa: ngekhodi", + password: "Inombolo yokuvula", + password_explain: + "Ukudala iinombolo yokuvula oyisebenzisayo ukucima ukugcina", + retype_password: "Phina inombolo yokuvula", + passwords_do_not_match: "Inombolo yokuvula azifani", + encrypt_storage: "Kubhala u kubhala", + lightning_settings: "Izixhobo zokukhanyisa", lightning_settings_explain: - 'Ukuxhuma kwi-node yakho ye-LND nceda ufake iLndHub' + - ' kwaye ufake iURL apha izicwangciso. Shiya kungenanto yokusebenzisa iLndHub (Indhub.io)', - save: 'ndoloza', - about: 'Malunga', - language: 'Ulwimi', - currency: 'Lwemali', + "Ukuxhuma kwi-node yakho ye-LND nceda ufake iLndHub" + + " kwaye ufake iURL apha izicwangciso. Shiya kungenanto yokusebenzisa iLndHub (Indhub.io)", + save: "ndoloza", + about: "Malunga", + language: "Ulwimi", + currency: "Lwemali" }, plausibledeniability: { - title: 'Ukuphika', + title: "Ukuphika", help: - 'Phantsi kweemeko unokunyaneliswa ukuba uchaze a ' + - 'inombolo yokuvula. Veles Wallet ukugcina imali yakho ikhuselekile, unokudala enye ' + - 'ukugcinwa kwekhowudi, ngegama eligqithisiweyo. Phantsi kwefuthe, ' + - 'unako ukutyhila le phasiwedi kumntu wesithatu. Ukuba ungenayo ' + - 'Veles Wallet, iya kuvula ukugcinwa kwetyala ‘entsha’. Oku kuya kubonakala ' + - 'Umlenze kumntu wesithathu kodwa uza kugcina ngasese ukugcinwa kwakho ' + - 'ngemali ekhuselekile..', + "Phantsi kweemeko unokunyaneliswa ukuba uchaze a " + + "inombolo yokuvula. Veles Wallet ukugcina imali yakho ikhuselekile, unokudala enye " + + "ukugcinwa kwekhowudi, ngegama eligqithisiweyo. Phantsi kwefuthe, " + + "unako ukutyhila le phasiwedi kumntu wesithatu. Ukuba ungenayo " + + "Veles Wallet, iya kuvula ukugcinwa kwetyala ‘entsha’. Oku kuya kubonakala " + + "Umlenze kumntu wesithathu kodwa uza kugcina ngasese ukugcinwa kwakho " + + "ngemali ekhuselekile..", help2: - 'Igumbi lokugcina elitsha liza kusebenza ngokupheleleyo, kwaye unako ukugcina okunye ‘ + ‘lxabiso elincinci apho likhangeleka ngakumbi.', - create_fake_storage: 'Ukudala igumbi lokugcina elifihlakeleyo', - go_back: 'Buya Umva', - create_password: 'Yenza inombolo yokuvula', + "Igumbi lokugcina elitsha liza kusebenza ngokupheleleyo, kwaye unako ukugcina okunye ‘ + ‘lxabiso elincinci apho likhangeleka ngakumbi.", + create_fake_storage: "Ukudala igumbi lokugcina elifihlakeleyo", + go_back: "Buya Umva", + create_password: "Yenza inombolo yokuvula", create_password_explanation: - 'Inombolo yakho yokuvula igumbi lokugcina inkohliso akumele ifane ne nombolo yokuvula igumbi lakho elinyanisekileyo', + "Inombolo yakho yokuvula igumbi lokugcina inkohliso akumele ifane ne nombolo yokuvula igumbi lakho elinyanisekileyo", password_should_not_match: - 'Inombolo yakho yokuvula igumbi lokugcina inkohliso akumele ifane ne nombolo yokuvula igumbi lakho elinyanisekileyo', - retype_password: 'Phinda inombolo yokuvula', - passwords_do_not_match: 'Inombolo yokuvula ayihambelani, zama kwakhona', - success: 'Iphumelele', + "Inombolo yakho yokuvula igumbi lokugcina inkohliso akumele ifane ne nombolo yokuvula igumbi lakho elinyanisekileyo", + retype_password: "Phinda inombolo yokuvula", + passwords_do_not_match: "Inombolo yokuvula ayihambelani, zama kwakhona", + success: "Iphumelele" }, lnd: { - title: 'lawula imali', - choose_source_wallet: 'Ukhethe ingxowa yomthombo', - refill_lnd_balance: 'Gcwalisa ingxowa yakho yemali', - refill: 'Gcwalisa', - withdraw: 'Khupha imali', - expired: 'Iphelewe lixesha', - placeholder: 'Invoyisi', - sameWalletAsInvoiceError: ': Awukwazi ukuhlawula i-invoyisi kunye ngengxowa oyisebenzisile ukudala leyo invoyisi.', + title: "lawula imali", + choose_source_wallet: "Ukhethe ingxowa yomthombo", + refill_lnd_balance: "Gcwalisa ingxowa yakho yemali", + refill: "Gcwalisa", + withdraw: "Khupha imali", + expired: "Iphelewe lixesha", + placeholder: "Invoyisi", + sameWalletAsInvoiceError: + ": Awukwazi ukuhlawula i-invoyisi kunye ngengxowa oyisebenzisile ukudala leyo invoyisi." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/cs_CZ.js b/loc/cs_CZ.js index ab1f3758c49..31c06cd1f62 100644 --- a/loc/cs_CZ.js +++ b/loc/cs_CZ.js @@ -1,243 +1,256 @@ module.exports = { _: { - storage_is_encrypted: 'Vaše úložiště je zašifrované. Zadejte heslo k odemčení', - enter_password: 'Zadejte heslo', - bad_password: 'Špatné heslo, prosím zkuste to znovu', - never: 'nikdy', - continue: 'Continue', - ok: 'OK', + storage_is_encrypted: + "Vaše úložiště je zašifrované. Zadejte heslo k odemčení", + enter_password: "Zadejte heslo", + bad_password: "Špatné heslo, prosím zkuste to znovu", + never: "nikdy", + continue: "Continue", + ok: "OK" }, wallets: { - select_wallet: 'Vyberte peněženku', - options: 'možnosti', - createBitcoinWallet: 'In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?', + select_wallet: "Vyberte peněženku", + options: "možnosti", + createBitcoinWallet: + "In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?", list: { - app_name: 'Veles Wallet', - title: 'peněženky', - header: 'Peněženka reprezentuje pár tajného (privátního) klíče a adresy' + 'kterou můžete sdílet, abyste získali mince', - add: 'Přidat peněženku', - create_a_wallet: 'Vytvořit peněženku', - create_a_wallet1: 'Je to zdarma a můžete vytvořit', - create_a_wallet2: 'tolik, kolik budete chtít', - latest_transaction: 'poslední transakce', - empty_txs1: 'Zde budou zobrazeny vaše transakce,', - empty_txs2: 'zatím žádné', + app_name: "Veles Wallet", + title: "peněženky", + header: + "Peněženka reprezentuje pár tajného (privátního) klíče a adresy" + + "kterou můžete sdílet, abyste získali mince", + add: "Přidat peněženku", + create_a_wallet: "Vytvořit peněženku", + create_a_wallet1: "Je to zdarma a můžete vytvořit", + create_a_wallet2: "tolik, kolik budete chtít", + latest_transaction: "poslední transakce", + empty_txs1: "Zde budou zobrazeny vaše transakce,", + empty_txs2: "zatím žádné", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Klikněte zde pro zakoupení Bitcoinu', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Klikněte zde pro zakoupení Bitcoinu" }, reorder: { - title: 'Seřadit peěženky', + title: "Seřadit peěženky" }, add: { - title: 'přidat peněženku', + title: "přidat peněženku", description: - 'Můžete naskenovat zálohovoanou papírovou peněženku (WIF - Wallet Import Format), nevo vytvořit novou peněženku. Segwit peněženky jsou podporovány standardně.', - scan: 'Skenovat', - create: 'Vytvořit', - label_new_segwit: 'Nová SegWit', - label_new_lightning: 'Nová Lightning', - wallet_name: 'název peněženky', - wallet_type: 'typ', - or: 'nebo', - import_wallet: 'Importovat peněženku', - imported: 'Importována', - coming_soon: 'Již brzy', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Můžete naskenovat zálohovoanou papírovou peněženku (WIF - Wallet Import Format), nevo vytvořit novou peněženku. Segwit peněženky jsou podporovány standardně.", + scan: "Skenovat", + create: "Vytvořit", + label_new_segwit: "Nová SegWit", + label_new_lightning: "Nová Lightning", + wallet_name: "název peněženky", + wallet_type: "typ", + or: "nebo", + import_wallet: "Importovat peněženku", + imported: "Importována", + coming_soon: "Již brzy", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Peněženka', - address: 'Adresa', - type: 'Typ', - label: 'Popisek', - destination: 'cíl', - description: 'Popis', - are_you_sure: 'Jste si jistý?', - yes_delete: 'Ano, smazat', - no_cancel: 'Ne, zrušit', - delete: 'Smazat', - save: 'Uložit', - delete_this_wallet: 'Smazat peněženku', - export_backup: 'Exportovat / zálohovat', - buy_bitcoin: 'Koupit Bitcoin', - show_xpub: 'Ukázat XPUB', + title: "Peněženka", + address: "Adresa", + type: "Typ", + label: "Popisek", + destination: "cíl", + description: "Popis", + are_you_sure: "Jste si jistý?", + yes_delete: "Ano, smazat", + no_cancel: "Ne, zrušit", + delete: "Smazat", + save: "Uložit", + delete_this_wallet: "Smazat peněženku", + export_backup: "Exportovat / zálohovat", + buy_bitcoin: "Koupit Bitcoin", + show_xpub: "Ukázat XPUB" }, export: { - title: 'exportovat peněženku', + title: "exportovat peněženku" }, xpub: { - title: 'XPUB peněženky', - copiedToClipboard: 'Zkopírováno do schránky.', + title: "XPUB peněženky", + copiedToClipboard: "Zkopírováno do schránky." }, import: { - title: 'importovat', + title: "importovat", explanation: - 'Zadejte zde svůj mnemonic seed, privátní klíč, WIF, nebo cokoliv co máte. Veles Wallet se pokusí uhodnout správný formát a naimportovat vaší peněženku', - imported: 'Importováno', - error: 'Chyba při importu. Prosím ujistěte se, že poskytnutá data jsou správná.', - success: 'Úspěch', - do_import: 'Importovat', - scan_qr: 'nebo raději naskenovat QR kód?', + "Zadejte zde svůj mnemonic seed, privátní klíč, WIF, nebo cokoliv co máte. Veles Wallet se pokusí uhodnout správný formát a naimportovat vaší peněženku", + imported: "Importováno", + error: + "Chyba při importu. Prosím ujistěte se, že poskytnutá data jsou správná.", + success: "Úspěch", + do_import: "Importovat", + scan_qr: "nebo raději naskenovat QR kód?" }, scanQrWif: { - go_back: 'Zpět', - cancel: 'Zrušit', - decoding: 'Dekóduji', - input_password: 'Vložte heslo', - password_explain: 'Toto je BIP38 zašifrovaný privátní klíč', - bad_password: 'Špatné heslo', - wallet_already_exists: 'Tato peněženka již existuje', - bad_wif: 'Špatný WIF', - imported_wif: 'Importovaný WIF ', - with_address: ' s adresou ', - imported_segwit: 'Importovaná SegWit', - imported_legacy: 'Importovaná Legacy', - imported_watchonly: 'Importovaná Watch-only', - }, + go_back: "Zpět", + cancel: "Zrušit", + decoding: "Dekóduji", + input_password: "Vložte heslo", + password_explain: "Toto je BIP38 zašifrovaný privátní klíč", + bad_password: "Špatné heslo", + wallet_already_exists: "Tato peněženka již existuje", + bad_wif: "Špatný WIF", + imported_wif: "Importovaný WIF ", + with_address: " s adresou ", + imported_segwit: "Importovaná SegWit", + imported_legacy: "Importovaná Legacy", + imported_watchonly: "Importovaná Watch-only" + } }, transactions: { list: { - tabBarLabel: 'Transakce', - title: 'transakce', - description: 'Seznam příchozích a odchozích transakcí vašich peněženek', - conf: 'potvrzení', + tabBarLabel: "Transakce", + title: "transakce", + description: "Seznam příchozích a odchozích transakcí vašich peněženek", + conf: "potvrzení" }, details: { - title: 'Transakce', - from: 'Input', - to: 'Output', - copy: 'Kopírovat', - transaction_details: 'Detaily transakce', - show_in_block_explorer: 'Ukázat v block exploreru', - }, + title: "Transakce", + from: "Input", + to: "Output", + copy: "Kopírovat", + transaction_details: "Detaily transakce", + show_in_block_explorer: "Ukázat v block exploreru" + } }, send: { - header: 'Poslat', + header: "Poslat", details: { - title: 'vytvořit transakci', - amount_field_is_not_valid: 'Čáskta není správně vyplněna', - fee_field_is_not_valid: 'Poplatek není správně vyplněn', - address_field_is_not_valid: 'Adresa není správně vyplněna', - total_exceeds_balance: 'Částka, kterou se snažíte poslat, přesahuje dostupný zůstatek.', - create_tx_error: 'Nastala chyba při vytváření transakce. Prosím ujistěte se, že adresa je platná.', - address: 'adresa', - amount_placeholder: 'částka k odeslání (v VLS)', - fee_placeholder: 'plus transakční poplatek (v VLS)', - note_placeholder: 'poznámka pro sebe', - cancel: 'Zrušit', - scan: 'Skenovat', - send: 'Poslat', - create: 'Vytvořit', - remaining_balance: 'Zbývající zůstatek', + title: "vytvořit transakci", + amount_field_is_not_valid: "Čáskta není správně vyplněna", + fee_field_is_not_valid: "Poplatek není správně vyplněn", + address_field_is_not_valid: "Adresa není správně vyplněna", + total_exceeds_balance: + "Částka, kterou se snažíte poslat, přesahuje dostupný zůstatek.", + create_tx_error: + "Nastala chyba při vytváření transakce. Prosím ujistěte se, že adresa je platná.", + address: "adresa", + amount_placeholder: "částka k odeslání (v VLS)", + fee_placeholder: "plus transakční poplatek (v VLS)", + note_placeholder: "poznámka pro sebe", + cancel: "Zrušit", + scan: "Skenovat", + send: "Poslat", + create: "Vytvořit", + remaining_balance: "Zbývající zůstatek" }, confirm: { - header: 'Potvrdit', - sendNow: 'Poslat hned', + header: "Potvrdit", + sendNow: "Poslat hned" }, success: { - done: 'Hotovo', + done: "Hotovo" }, create: { - details: 'Detaily', - title: 'vytvořit transakci', - error: 'Chyba při vytváření transakce. Nesprávná adresa nebo částka?', - go_back: 'Zpět', - this_is_hex: 'Toto je vaše transakce, podepsána a připravena k odeslání do sítě.', - to: 'To', - amount: 'Částka', - fee: 'Poplatek', - tx_size: 'velikost transakce', - satoshi_per_byte: 'Satoshi/byte', - memo: 'Popisek', - broadcast: 'Odeslat do sítě', - not_enough_fee: 'Nedostatečný poplatek. Zvyšte poplatek.', - }, + details: "Detaily", + title: "vytvořit transakci", + error: "Chyba při vytváření transakce. Nesprávná adresa nebo částka?", + go_back: "Zpět", + this_is_hex: + "Toto je vaše transakce, podepsána a připravena k odeslání do sítě.", + to: "To", + amount: "Částka", + fee: "Poplatek", + tx_size: "velikost transakce", + satoshi_per_byte: "Satoshi/byte", + memo: "Popisek", + broadcast: "Odeslat do sítě", + not_enough_fee: "Nedostatečný poplatek. Zvyšte poplatek." + } }, receive: { - header: 'Přijmout', + header: "Přijmout", details: { - title: 'Sdílejte tuto adresu s plátcem', - share: 'sdílet', - copiedToClipboard: 'Zkopírováno do schránky.', - label: 'Popis', - create: 'Create', - setAmount: 'Přijmout částku...', + title: "Sdílejte tuto adresu s plátcem", + share: "sdílet", + copiedToClipboard: "Zkopírováno do schránky.", + label: "Popis", + create: "Create", + setAmount: "Přijmout částku..." }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Koupit Bitcoin', - tap_your_address: 'Klikněte na svojí adresu pro zkopírování do schránky:', - copied: 'Zkopírováno do schránky.', + header: "Koupit Bitcoin", + tap_your_address: "Klikněte na svojí adresu pro zkopírování do schránky:", + copied: "Zkopírováno do schránky." }, settings: { - header: 'nastavení', - plausible_deniability: 'Plausible deniability...', - storage_not_encrypted: 'Uložiště: nezašifrováno', - storage_encrypted: 'Úložiště: zašifrováno', - password: 'Heslo', - password_explain: 'Vytořte si heslo k zašifrování úložiště.', - retype_password: 'Heslo znovu', - passwords_do_not_match: 'Hesla se neshodují', - encrypt_storage: 'Zašifrovat úložiště', - lightning_settings: 'Lightning settings', + header: "nastavení", + plausible_deniability: "Plausible deniability...", + storage_not_encrypted: "Uložiště: nezašifrováno", + storage_encrypted: "Úložiště: zašifrováno", + password: "Heslo", + password_explain: "Vytořte si heslo k zašifrování úložiště.", + retype_password: "Heslo znovu", + passwords_do_not_match: "Hesla se neshodují", + encrypt_storage: "Zašifrovat úložiště", + lightning_settings: "Lightning settings", lightning_settings_explain: - 'To connect to your own LND node please install LndHub' + - ' and put its URL here in settings. Leave blank to use default ' + - 'ndHub\n (lndhub.io)', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'save', - about: 'O Veles Wallet', - language: 'Jazyk', - currency: 'Měna', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "To connect to your own LND node please install LndHub" + + " and put its URL here in settings. Leave blank to use default " + + "ndHub\n (lndhub.io)", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "save", + about: "O Veles Wallet", + language: "Jazyk", + currency: "Měna", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Plausible Deniability', + title: "Plausible Deniability", help: - 'Za určitých okolností můžete být donuceni k prozrazení vašeho hesla.' + - 'K zajištění bezpečností vašich prostředků, Veles Wallet může vytvořit' + - 'další zašifrované úložiště s rozdílný heslem. V případě potřeby' + - 'můžete toto heslo dát třetí straně. Pokud bude zadáno do Veles Wallet,' + + "Za určitých okolností můžete být donuceni k prozrazení vašeho hesla." + + "K zajištění bezpečností vašich prostředků, Veles Wallet může vytvořit" + + "další zašifrované úložiště s rozdílný heslem. V případě potřeby" + + "můžete toto heslo dát třetí straně. Pokud bude zadáno do Veles Wallet," + 'odemkne nové "falešné" úložiště. Toto bude vypadat legitimně, ale' + - 'udrží vaše pravé hlavní úložiště v bezpečí.', - help2: 'Nové úložiště bude plně funkční, můžete na něj uložit minimální částku, aby vypadalo více uvěřitelně.', - create_fake_storage: 'Vytvořit falešné zašifrované úložiště', - go_back: 'Zpět', - create_password: 'Vytvořit heslo', - create_password_explanation: 'Heslo k falešnému úložišti nesmí být stejné jako heslo k hlavnímu úložišti', - password_should_not_match: 'Heslo k falešnému úložišti nesmí být stejné jako heslo k hlavnímu úložišti', - retype_password: 'Heslo znovu', - passwords_do_not_match: 'Hesla se neshodují, zkuste to znovu', - success: 'Úspěch', + "udrží vaše pravé hlavní úložiště v bezpečí.", + help2: + "Nové úložiště bude plně funkční, můžete na něj uložit minimální částku, aby vypadalo více uvěřitelně.", + create_fake_storage: "Vytvořit falešné zašifrované úložiště", + go_back: "Zpět", + create_password: "Vytvořit heslo", + create_password_explanation: + "Heslo k falešnému úložišti nesmí být stejné jako heslo k hlavnímu úložišti", + password_should_not_match: + "Heslo k falešnému úložišti nesmí být stejné jako heslo k hlavnímu úložišti", + retype_password: "Heslo znovu", + passwords_do_not_match: "Hesla se neshodují, zkuste to znovu", + success: "Úspěch" }, lnd: { - title: 'spravovat zůstatek', - choose_source_wallet: 'Vyberte zdrojovou peněženku', - refill_lnd_balance: 'Doplnit zůstatek na Lightning peněžence', - refill: 'Doplnit', - withdraw: 'Vybrat', - expired: 'Expirováno', - placeholder: 'Invoice', - sameWalletAsInvoiceError: 'You can not pay an invoice with the same wallet used to create it.', + title: "spravovat zůstatek", + choose_source_wallet: "Vyberte zdrojovou peněženku", + refill_lnd_balance: "Doplnit zůstatek na Lightning peněžence", + refill: "Doplnit", + withdraw: "Vybrat", + expired: "Expirováno", + placeholder: "Invoice", + sameWalletAsInvoiceError: + "You can not pay an invoice with the same wallet used to create it." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/da_DK.js b/loc/da_DK.js index 521271813ca..0b7d6cff4cf 100644 --- a/loc/da_DK.js +++ b/loc/da_DK.js @@ -1,242 +1,257 @@ module.exports = { _: { - storage_is_encrypted: 'Lageret er krypteret. Indtast adgangskode for at dekryptere', - enter_password: 'Indtast adgangskode', - bad_password: 'Forkert adgangskode, prøv igen', - never: 'aldrig', - continue: 'Continue', - ok: 'OK', + storage_is_encrypted: + "Lageret er krypteret. Indtast adgangskode for at dekryptere", + enter_password: "Indtast adgangskode", + bad_password: "Forkert adgangskode, prøv igen", + never: "aldrig", + continue: "Continue", + ok: "OK" }, wallets: { - select_wallet: 'Vælg wallet', - options: 'valgmuligheder', - createBitcoinWallet: 'In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?', + select_wallet: "Vælg wallet", + options: "valgmuligheder", + createBitcoinWallet: + "In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?", list: { - app_name: 'Veles Wallet', - title: 'wallets', - header: 'En wallet består af par af hemmelige (private nøgler) og en adresse' + 'som du kan dele med andre for at modtage coins.', - add: 'Tilføj Wallet', - create_a_wallet: 'Opret en wallet', - create_a_wallet1: 'Det er helt gratis og du kan oprette', - create_a_wallet2: 'lige så mange du vil', - latest_transaction: 'seneste transaktion', - empty_txs1: 'Dine transaktioner vil blive vist her,', - empty_txs2: 'ingen endnu', + app_name: "Veles Wallet", + title: "wallets", + header: + "En wallet består af par af hemmelige (private nøgler) og en adresse" + + "som du kan dele med andre for at modtage coins.", + add: "Tilføj Wallet", + create_a_wallet: "Opret en wallet", + create_a_wallet1: "Det er helt gratis og du kan oprette", + create_a_wallet2: "lige så mange du vil", + latest_transaction: "seneste transaktion", + empty_txs1: "Dine transaktioner vil blive vist her,", + empty_txs2: "ingen endnu", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Tryk her for at købe Bitcoin', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Tryk her for at købe Bitcoin" }, reorder: { - title: 'Ændre rækkefølgen af wallets', + title: "Ændre rækkefølgen af wallets" }, add: { - title: 'Tilføj wallet', + title: "Tilføj wallet", description: - 'Du kan enten scanne en backup papir wallet (i et WIF - Wallet Import Format), eller oprette en ny wallet. Segwit wallets er understøttet som standard.', - scan: 'Scan', - create: 'Opret', - label_new_segwit: 'Ny SegWit', - label_new_lightning: 'Ny Lightning', - wallet_name: 'wallet navn', - wallet_type: 'type', - or: 'eller', - import_wallet: 'Importer wallet', - imported: 'Importeret', - coming_soon: 'Kommer snart', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Du kan enten scanne en backup papir wallet (i et WIF - Wallet Import Format), eller oprette en ny wallet. Segwit wallets er understøttet som standard.", + scan: "Scan", + create: "Opret", + label_new_segwit: "Ny SegWit", + label_new_lightning: "Ny Lightning", + wallet_name: "wallet navn", + wallet_type: "type", + or: "eller", + import_wallet: "Importer wallet", + imported: "Importeret", + coming_soon: "Kommer snart", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Wallet', - address: 'Adresse', - type: 'Type', - label: 'Etiket', - destination: 'destination', - description: 'bskrivelse', - are_you_sure: 'Er du sikker?', - yes_delete: 'Ja, slet', - no_cancel: 'Nej, annuller', - delete: 'Slet', - save: 'Gem', - delete_this_wallet: 'Slet denne wallet', - export_backup: 'Eksporter / backup', - buy_bitcoin: 'Køb Bitcoin', - show_xpub: 'Vis wallet XPUB', + title: "Wallet", + address: "Adresse", + type: "Type", + label: "Etiket", + destination: "destination", + description: "bskrivelse", + are_you_sure: "Er du sikker?", + yes_delete: "Ja, slet", + no_cancel: "Nej, annuller", + delete: "Slet", + save: "Gem", + delete_this_wallet: "Slet denne wallet", + export_backup: "Eksporter / backup", + buy_bitcoin: "Køb Bitcoin", + show_xpub: "Vis wallet XPUB" }, export: { - title: 'wallet eksport', + title: "wallet eksport" }, xpub: { - title: 'wallet XPUB', - copiedToClipboard: 'Kopieret til udklipsholder.', + title: "wallet XPUB", + copiedToClipboard: "Kopieret til udklipsholder." }, import: { - title: 'importer', + title: "importer", explanation: - 'Indtast din huskeregel, private nøgle, WIF, eller hvad du end har. Veles Wallet vil forsøge at gætte det rigtige format og importere din wallet', - imported: 'Importeret', - error: 'Importen lykkedes ikke. Er det en gyldig nøgle?', - success: 'Succes', - do_import: 'Importer', - scan_qr: 'eller scan QR kode istedet?', + "Indtast din huskeregel, private nøgle, WIF, eller hvad du end har. Veles Wallet vil forsøge at gætte det rigtige format og importere din wallet", + imported: "Importeret", + error: "Importen lykkedes ikke. Er det en gyldig nøgle?", + success: "Succes", + do_import: "Importer", + scan_qr: "eller scan QR kode istedet?" }, scanQrWif: { - go_back: 'Tilbage', - cancel: 'Annuller', - decoding: 'Afkoder', - input_password: 'Indtast adgangskode', - password_explain: 'Dette er en BIP38 krypteret privat nøgle', - bad_password: 'Forkert adgangkode', - wallet_already_exists: 'En sådan wallet eksisterer allerede', - bad_wif: 'Forkert WIF', - imported_wif: 'Importeret WIF ', - with_address: ' med adresse ', - imported_segwit: 'Importeret SegWit', - imported_legacy: 'Importeret Legacy', - imported_watchonly: 'Importeret Watch-only', - }, + go_back: "Tilbage", + cancel: "Annuller", + decoding: "Afkoder", + input_password: "Indtast adgangskode", + password_explain: "Dette er en BIP38 krypteret privat nøgle", + bad_password: "Forkert adgangkode", + wallet_already_exists: "En sådan wallet eksisterer allerede", + bad_wif: "Forkert WIF", + imported_wif: "Importeret WIF ", + with_address: " med adresse ", + imported_segwit: "Importeret SegWit", + imported_legacy: "Importeret Legacy", + imported_watchonly: "Importeret Watch-only" + } }, transactions: { list: { - tabBarLabel: 'Transaktioner', - title: 'transaktioner', - description: 'En liste af indgåeende og udgående transaktioner i dine wallets', - conf: 'conf', + tabBarLabel: "Transaktioner", + title: "transaktioner", + description: + "En liste af indgåeende og udgående transaktioner i dine wallets", + conf: "conf" }, details: { - title: 'Transaktion', - from: 'Fra', - to: 'Til', - copy: 'Kopier', - transaction_details: 'Transaktions detaljer', - show_in_block_explorer: 'Vis i block-explorer', - }, + title: "Transaktion", + from: "Fra", + to: "Til", + copy: "Kopier", + transaction_details: "Transaktions detaljer", + show_in_block_explorer: "Vis i block-explorer" + } }, send: { - header: 'Send', + header: "Send", details: { - title: 'opret transaktion', - amount_field_is_not_valid: 'Beløbsfeltet er ikke gyldigt', - fee_field_is_not_valid: 'Gebyr feltet er ikke gyldigt', - address_field_is_not_valid: 'Adresse felt er ikke gyldigt', - total_exceeds_balance: 'Beløbet du prøver at sende er større end din kontosaldo.', - create_tx_error: 'Der skete en fejl ved oprettelse af transaktionen. Check om addressen er gyldig.', - address: 'adresse', - amount_placeholder: 'beløb der skal sendes (i VLS)', - fee_placeholder: 'plus transaktionsgebyr (i VLS)', - note_placeholder: 'Notat til eget brug', - cancel: 'Annuller', - scan: 'Scan', - send: 'Send', - create: 'Opret', - remaining_balance: 'Resterende saldo', + title: "opret transaktion", + amount_field_is_not_valid: "Beløbsfeltet er ikke gyldigt", + fee_field_is_not_valid: "Gebyr feltet er ikke gyldigt", + address_field_is_not_valid: "Adresse felt er ikke gyldigt", + total_exceeds_balance: + "Beløbet du prøver at sende er større end din kontosaldo.", + create_tx_error: + "Der skete en fejl ved oprettelse af transaktionen. Check om addressen er gyldig.", + address: "adresse", + amount_placeholder: "beløb der skal sendes (i VLS)", + fee_placeholder: "plus transaktionsgebyr (i VLS)", + note_placeholder: "Notat til eget brug", + cancel: "Annuller", + scan: "Scan", + send: "Send", + create: "Opret", + remaining_balance: "Resterende saldo" }, confirm: { - header: 'Bekræft', - sendNow: 'Send nu', + header: "Bekræft", + sendNow: "Send nu" }, success: { - done: 'Udført', + done: "Udført" }, create: { - details: 'Detaljer', - title: 'opret transaktion', - error: 'Der skete en fejl ved oprettelse af transaktionen. Er addresssen og beløbet korrekt?', - go_back: 'Tilbage', - this_is_hex: 'Dette er transaktion hex, klar til at sende ud til netværket.', - to: 'Til', - amount: 'Beløb', - fee: 'Gebyr', - tx_size: 'TX størrelse', - satoshi_per_byte: 'Satoshi per byte', - memo: 'Notat', - broadcast: 'Transmitter', - not_enough_fee: 'Gebyret er ikke højt nok. Forhøj gebyret.', - }, + details: "Detaljer", + title: "opret transaktion", + error: + "Der skete en fejl ved oprettelse af transaktionen. Er addresssen og beløbet korrekt?", + go_back: "Tilbage", + this_is_hex: + "Dette er transaktion hex, klar til at sende ud til netværket.", + to: "Til", + amount: "Beløb", + fee: "Gebyr", + tx_size: "TX størrelse", + satoshi_per_byte: "Satoshi per byte", + memo: "Notat", + broadcast: "Transmitter", + not_enough_fee: "Gebyret er ikke højt nok. Forhøj gebyret." + } }, receive: { - header: 'Modtag', + header: "Modtag", details: { - title: 'Del denne adresse med betaleren', - share: 'del', - copiedToClipboard: 'Kopieret til udklipsholder.', - label: 'Beskrivelse', - create: 'Create', - setAmount: 'Modtag med beløb', + title: "Del denne adresse med betaleren", + share: "del", + copiedToClipboard: "Kopieret til udklipsholder.", + label: "Beskrivelse", + create: "Create", + setAmount: "Modtag med beløb" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Køb Bitcoin', - tap_your_address: 'Tryk på addressen og kopier den til udklipsholder:', - copied: 'Kopieret til udklipsholder!', + header: "Køb Bitcoin", + tap_your_address: "Tryk på addressen og kopier den til udklipsholder:", + copied: "Kopieret til udklipsholder!" }, settings: { - header: 'indstillinger', - plausible_deniability: 'Sandsynlig benægtelse...', - storage_not_encrypted: 'Lager: ikke krypteret', - storage_encrypted: 'Lager: krypteret', - password: 'Adgangskode', - password_explain: 'Indtast den adgangskode du vil bruge til at kryptere lageret', - retype_password: 'Gentag adgangskoden', - passwords_do_not_match: 'Adgangskoden er ikke den samme', - encrypt_storage: 'Krypter lager', - lightning_settings: 'Lightning settings', + header: "indstillinger", + plausible_deniability: "Sandsynlig benægtelse...", + storage_not_encrypted: "Lager: ikke krypteret", + storage_encrypted: "Lager: krypteret", + password: "Adgangskode", + password_explain: + "Indtast den adgangskode du vil bruge til at kryptere lageret", + retype_password: "Gentag adgangskoden", + passwords_do_not_match: "Adgangskoden er ikke den samme", + encrypt_storage: "Krypter lager", + lightning_settings: "Lightning settings", lightning_settings_explain: - 'To connect to your own LND node please install LndHub' + - ' and put its URL here in settings. Leave blank to use default ' + - 'ndHub\n (lndhub.io)', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'save', - about: 'Andet', - language: 'Sprog', - currency: 'Valuta', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "To connect to your own LND node please install LndHub" + + " and put its URL here in settings. Leave blank to use default " + + "ndHub\n (lndhub.io)", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "save", + about: "Andet", + language: "Sprog", + currency: "Valuta", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Sandsynlig benægtelse', + title: "Sandsynlig benægtelse", help: - 'Under visse omstændighder, kan du blive tvunget til at give din ' + - 'adgangskode. For at beskytte dine coins kan du med Veles Wallet lave ' + - 'et falsk krypteret lager, med en anden kode. I en presset situation, ' + - 'kan du give denne adgangskode istedet. Hvis denne kode indtastes i ' + - 'Veles Wallet, vil brugeren se den alternative wallet. Det vil se helt' + - 'legitimt ud for andre, og dermed beskytte din originale wallet og ' + - 'dine coins.', - help2: 'Det nye lager vil være fuldt funktionsdygtigt, og du kan evt have nogle ' + 'småbeløb så det ser troværdigt ud.', - create_fake_storage: 'Opret falsk kryopteret lager', - go_back: 'tilbage', - create_password: 'Opret adgangskode', - create_password_explanation: 'Adgangskoden til det falske lager må ikke være den samme som den du bruger til det rigtige lager', - password_should_not_match: 'Adgangskoden til det falske lager må ikke være den samme som den du bruger til det rigtige lager', - retype_password: 'Indtast adgangskoden igen', - passwords_do_not_match: 'Adgangskoden er ikke den samme, prøv igen', - success: 'Succes', + "Under visse omstændighder, kan du blive tvunget til at give din " + + "adgangskode. For at beskytte dine coins kan du med Veles Wallet lave " + + "et falsk krypteret lager, med en anden kode. I en presset situation, " + + "kan du give denne adgangskode istedet. Hvis denne kode indtastes i " + + "Veles Wallet, vil brugeren se den alternative wallet. Det vil se helt" + + "legitimt ud for andre, og dermed beskytte din originale wallet og " + + "dine coins.", + help2: + "Det nye lager vil være fuldt funktionsdygtigt, og du kan evt have nogle " + + "småbeløb så det ser troværdigt ud.", + create_fake_storage: "Opret falsk kryopteret lager", + go_back: "tilbage", + create_password: "Opret adgangskode", + create_password_explanation: + "Adgangskoden til det falske lager må ikke være den samme som den du bruger til det rigtige lager", + password_should_not_match: + "Adgangskoden til det falske lager må ikke være den samme som den du bruger til det rigtige lager", + retype_password: "Indtast adgangskoden igen", + passwords_do_not_match: "Adgangskoden er ikke den samme, prøv igen", + success: "Succes" }, lnd: { - title: 'Administration', - placeholder: 'Invoice', - choose_source_wallet: 'Vælge en wallet', - refill_lnd_balance: 'Genopfyld Lightning wallet', - refill: 'Genopfyld', - withdraw: 'Træk coins tilbage', + title: "Administration", + placeholder: "Invoice", + choose_source_wallet: "Vælge en wallet", + refill_lnd_balance: "Genopfyld Lightning wallet", + refill: "Genopfyld", + withdraw: "Træk coins tilbage" }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/de_DE.js b/loc/de_DE.js index 63316da265d..d189afcfbd7 100644 --- a/loc/de_DE.js +++ b/loc/de_DE.js @@ -1,247 +1,259 @@ module.exports = { _: { - storage_is_encrypted: 'Dein Speicher ist verschlüsselt. Zum Entschlüsseln wird ein Passwort benötigt.', - enter_password: 'Gib das Passwort ein', - bad_password: 'Fasches Passwort, nächster Versuch', - never: 'nie', - continue: 'Weiter', - ok: 'OK', + storage_is_encrypted: + "Dein Speicher ist verschlüsselt. Zum Entschlüsseln wird ein Passwort benötigt.", + enter_password: "Gib das Passwort ein", + bad_password: "Fasches Passwort, nächster Versuch", + never: "nie", + continue: "Weiter", + ok: "OK" }, wallets: { - select_wallet: 'Wähle eine Wallet', - options: 'Einstellungen', + select_wallet: "Wähle eine Wallet", + options: "Einstellungen", createBitcoinWallet: - 'Um eine Lightning wallet zu verwenden, muss erstmal eine Bitcoin Wallet eingerichtet werden. Bitte erstell oder importier eine Bitcoin Wallet.', + "Um eine Lightning wallet zu verwenden, muss erstmal eine Bitcoin Wallet eingerichtet werden. Bitte erstell oder importier eine Bitcoin Wallet.", list: { - app_name: 'Veles Wallet', - title: 'Wallets', + app_name: "Veles Wallet", + title: "Wallets", header: - 'Eine Wallet spiegelt ein Paar kryptographische Schlüssel wider. Einen geheimen Schlüseel und eine Adresse als öffentlichen Schlüssel. Den öffentlichen Schlüssel kann man zum Empfang von Bitcoin teilen.', - add: 'Wallet hinzufügen', - create_a_wallet: 'Wallet erstellen', - create_a_wallet1: 'Es ist kostenlos und du kannst', - create_a_wallet2: 'so viele Wallets erstellen, wie du möchtest', - latest_transaction: 'Lezte Transaktion', - empty_txs1: 'Deine Transaktionen erscheinen hier', - empty_txs2: 'Noch keine Transaktionen', + "Eine Wallet spiegelt ein Paar kryptographische Schlüssel wider. Einen geheimen Schlüseel und eine Adresse als öffentlichen Schlüssel. Den öffentlichen Schlüssel kann man zum Empfang von Bitcoin teilen.", + add: "Wallet hinzufügen", + create_a_wallet: "Wallet erstellen", + create_a_wallet1: "Es ist kostenlos und du kannst", + create_a_wallet2: "so viele Wallets erstellen, wie du möchtest", + latest_transaction: "Lezte Transaktion", + empty_txs1: "Deine Transaktionen erscheinen hier", + empty_txs2: "Noch keine Transaktionen", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Klicke hier, um Bitcoin zu kaufen', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Klicke hier, um Bitcoin zu kaufen" }, reorder: { - title: 'Wallets neu ordnen', + title: "Wallets neu ordnen" }, add: { - title: 'Wallet hinzufügen', + title: "Wallet hinzufügen", description: - 'Du kannst entweder ein Backup einer Paper-Wallet einscannen (im WIF - Wallet Import Format) oder eine neue Wallet erstellen. SegWit Wallets werden standardmäßig unterstützt.', - scan: 'Scannen', - create: 'Erstellen', - label_new_segwit: 'Neue SegWit Wallet', - label_new_lightning: 'Neue Lightning Wallet', - wallet_name: 'Wallet Name', - wallet_type: 'Typ', - or: 'oder', - import_wallet: 'Wallet importieren', - imported: 'Importiert', - coming_soon: 'Demnächst verfügbar', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Du kannst entweder ein Backup einer Paper-Wallet einscannen (im WIF - Wallet Import Format) oder eine neue Wallet erstellen. SegWit Wallets werden standardmäßig unterstützt.", + scan: "Scannen", + create: "Erstellen", + label_new_segwit: "Neue SegWit Wallet", + label_new_lightning: "Neue Lightning Wallet", + wallet_name: "Wallet Name", + wallet_type: "Typ", + or: "oder", + import_wallet: "Wallet importieren", + imported: "Importiert", + coming_soon: "Demnächst verfügbar", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Wallet', - address: 'Adresse', - type: 'Typ', - label: 'Bezeichnung', - destination: 'Zieladresse', - description: 'Beschreibung', - are_you_sure: 'Bist du dir sicher??', - yes_delete: 'Ja, löschen', - no_cancel: 'Nein, abbrechnen', - delete: 'Löschen', - save: 'Sichern', - delete_this_wallet: 'Lösche diese Wallet', - export_backup: 'Exportieren / Backup', - buy_bitcoin: 'Bitcoin kaufen', - show_xpub: 'Wallet XPUB zeigen', + title: "Wallet", + address: "Adresse", + type: "Typ", + label: "Bezeichnung", + destination: "Zieladresse", + description: "Beschreibung", + are_you_sure: "Bist du dir sicher??", + yes_delete: "Ja, löschen", + no_cancel: "Nein, abbrechnen", + delete: "Löschen", + save: "Sichern", + delete_this_wallet: "Lösche diese Wallet", + export_backup: "Exportieren / Backup", + buy_bitcoin: "Bitcoin kaufen", + show_xpub: "Wallet XPUB zeigen" }, export: { - title: 'Wallet exportieren', + title: "Wallet exportieren" }, xpub: { - title: 'Wallet XPUB', - copiedToClipboard: 'In die Zwischenablage kopiert.', + title: "Wallet XPUB", + copiedToClipboard: "In die Zwischenablage kopiert." }, import: { - title: 'Importieren', + title: "Importieren", explanation: - 'Gib hier deine mnemonische Phrase, deinen privaten Schlüssel, WIF oder worüber du auch immer verfügst ein. Veles Wallet wird bestmöglich dein Format interpretieren und die Wallet importieren', - imported: 'Importiert', - error: 'Fehler beim Import. Ist die Eingabe korrekt?', - success: 'Erfolg', - do_import: 'Importieren', - scan_qr: 'oder QR-Code scannen?', + "Gib hier deine mnemonische Phrase, deinen privaten Schlüssel, WIF oder worüber du auch immer verfügst ein. Veles Wallet wird bestmöglich dein Format interpretieren und die Wallet importieren", + imported: "Importiert", + error: "Fehler beim Import. Ist die Eingabe korrekt?", + success: "Erfolg", + do_import: "Importieren", + scan_qr: "oder QR-Code scannen?" }, scanQrWif: { - go_back: 'Zurück', - cancel: 'Abbrechen', - decoding: 'Entschlüsseln', - input_password: 'Passwort eingeben', - password_explain: 'Das ist ein mit BIP38 verschlüsselter geheimer Schlüssel', - bad_password: 'Falsches Passwort', - wallet_already_exists: 'Diese Wallet existiert bereits', - bad_wif: 'Falsches WIF', - imported_wif: 'WIF importiert', - with_address: ' mit Adresse ', - imported_segwit: 'SegWit importiert', - imported_legacy: 'Legacy importiert', - imported_watchonly: 'Watch-Only importiert', - }, + go_back: "Zurück", + cancel: "Abbrechen", + decoding: "Entschlüsseln", + input_password: "Passwort eingeben", + password_explain: + "Das ist ein mit BIP38 verschlüsselter geheimer Schlüssel", + bad_password: "Falsches Passwort", + wallet_already_exists: "Diese Wallet existiert bereits", + bad_wif: "Falsches WIF", + imported_wif: "WIF importiert", + with_address: " mit Adresse ", + imported_segwit: "SegWit importiert", + imported_legacy: "Legacy importiert", + imported_watchonly: "Watch-Only importiert" + } }, transactions: { list: { - tabBarLabel: 'Transaktionen', - title: 'Transaktionen', - description: 'Eine Liste eingehender oder ausgehender Transaktionen deiner Wallets', - conf: 'conf', + tabBarLabel: "Transaktionen", + title: "Transaktionen", + description: + "Eine Liste eingehender oder ausgehender Transaktionen deiner Wallets", + conf: "conf" }, details: { - title: 'Transaktionen', - from: 'Eingehend', - to: 'Ausgehend', - copy: 'Kopieren', - transaction_details: 'Details', - show_in_block_explorer: 'Im Block-Explorer zeigen', - }, + title: "Transaktionen", + from: "Eingehend", + to: "Ausgehend", + copy: "Kopieren", + transaction_details: "Details", + show_in_block_explorer: "Im Block-Explorer zeigen" + } }, send: { - header: 'Senden', + header: "Senden", details: { - title: 'Transaktion erstellen', - amount_field_is_not_valid: 'Betrageingabe ist nicht korrekt', - fee_field_is_not_valid: 'Gebühreingabe ist nicht korrekt', - address_field_is_not_valid: 'Adresseingabe ist nicht korrekt', - total_exceeds_balance: 'Der zu sendende Betrag ist größer als der verfügbare Betrag.', - create_tx_error: 'Fehler beim Erstellen der Transaktion. Bitte stelle sicher, dass die Adresse korrekt ist.', - address: 'Adresse', - amount_placeholder: 'Betrag (in VLS)', - fee_placeholder: 'plus Gebühr (in VLS)', - note_placeholder: 'Notiz', - cancel: 'Abbrechen', - scan: 'Scan', - send: 'Senden', - create: 'Erstellen', - remaining_balance: 'Verfügbarer Betrag', + title: "Transaktion erstellen", + amount_field_is_not_valid: "Betrageingabe ist nicht korrekt", + fee_field_is_not_valid: "Gebühreingabe ist nicht korrekt", + address_field_is_not_valid: "Adresseingabe ist nicht korrekt", + total_exceeds_balance: + "Der zu sendende Betrag ist größer als der verfügbare Betrag.", + create_tx_error: + "Fehler beim Erstellen der Transaktion. Bitte stelle sicher, dass die Adresse korrekt ist.", + address: "Adresse", + amount_placeholder: "Betrag (in VLS)", + fee_placeholder: "plus Gebühr (in VLS)", + note_placeholder: "Notiz", + cancel: "Abbrechen", + scan: "Scan", + send: "Senden", + create: "Erstellen", + remaining_balance: "Verfügbarer Betrag" }, confirm: { - header: 'Bestätigen', - sendNow: 'Jetzt senden', + header: "Bestätigen", + sendNow: "Jetzt senden" }, success: { - done: 'Fertig', + done: "Fertig" }, create: { - details: 'Details', - title: 'Transaktion erstellen', - error: 'Fehler beim Erstellen der Transaktion. Falsche Adresse oder Betrag?', - go_back: 'Zurück', - this_is_hex: 'Das ist die hexadezimale Darstellung der signierten Transaktion und bereit zum Übertragen an das Netzwerk', - to: 'An', - amount: 'Betrag', - fee: 'Gebühr', - tx_size: 'Größe', - satoshi_per_byte: 'Satoshi pro Byte', - memo: 'Memo', - broadcast: 'Übertragen', - not_enough_fee: 'Gebühr zu gering. Erhöhe die Gebühr', - }, + details: "Details", + title: "Transaktion erstellen", + error: + "Fehler beim Erstellen der Transaktion. Falsche Adresse oder Betrag?", + go_back: "Zurück", + this_is_hex: + "Das ist die hexadezimale Darstellung der signierten Transaktion und bereit zum Übertragen an das Netzwerk", + to: "An", + amount: "Betrag", + fee: "Gebühr", + tx_size: "Größe", + satoshi_per_byte: "Satoshi pro Byte", + memo: "Memo", + broadcast: "Übertragen", + not_enough_fee: "Gebühr zu gering. Erhöhe die Gebühr" + } }, receive: { - header: 'Erhalten', + header: "Erhalten", details: { - title: 'Teile diese Adresse mit dem Zahlenden', - share: 'Teilen', - copiedToClipboard: 'In die Zwischenablage kopiert.', - label: 'Beschreibung', - create: 'Create', - setAmount: 'Zu erhaltender Betrag', + title: "Teile diese Adresse mit dem Zahlenden", + share: "Teilen", + copiedToClipboard: "In die Zwischenablage kopiert.", + label: "Beschreibung", + create: "Create", + setAmount: "Zu erhaltender Betrag" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Kaufe Bitcoin', - tap_your_address: 'Adresse antippen, um sie in die Zwischenablage zu kopieren:', - copied: 'In die Zwischenablage kopiert!', + header: "Kaufe Bitcoin", + tap_your_address: + "Adresse antippen, um sie in die Zwischenablage zu kopieren:", + copied: "In die Zwischenablage kopiert!" }, settings: { - header: 'Einstellungen', - plausible_deniability: 'Glaubhafte Täuschung...', - storage_not_encrypted: 'Speicher nicht verschlüsselt', - storage_encrypted: 'Speicher verschlüsselt', - password: 'Passwort', - password_explain: 'Erstelle das Passwort zum Entschlüsseln des Speichers', - retype_password: 'Passwort wiederholen', - passwords_do_not_match: 'Passwörter stimmen nicht überein', - encrypt_storage: 'Speicher verschlüsseln', - lightning_settings: 'Lightning Einstellungen', + header: "Einstellungen", + plausible_deniability: "Glaubhafte Täuschung...", + storage_not_encrypted: "Speicher nicht verschlüsselt", + storage_encrypted: "Speicher verschlüsselt", + password: "Passwort", + password_explain: "Erstelle das Passwort zum Entschlüsseln des Speichers", + retype_password: "Passwort wiederholen", + passwords_do_not_match: "Passwörter stimmen nicht überein", + encrypt_storage: "Speicher verschlüsseln", + lightning_settings: "Lightning Einstellungen", lightning_settings_explain: - 'Bitte installier Lndhub, um mit deiner eigenen LND Node zu verbinden' + - ' und setz seine URL hier in den Einstellungen. Lass das Feld leer, um Standard- ' + - 'LndHub\n (lndhub.io) zu verwenden', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Speichern', - about: 'Über', - language: 'Sprache', - currency: 'Währung', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Bitte installier Lndhub, um mit deiner eigenen LND Node zu verbinden" + + " und setz seine URL hier in den Einstellungen. Lass das Feld leer, um Standard- " + + "LndHub\n (lndhub.io) zu verwenden", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Speichern", + about: "Über", + language: "Sprache", + currency: "Währung", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Glaubhafte Täuschung', + title: "Glaubhafte Täuschung", help: - 'Unter bestimmten Umständen könntest du dazu gezwungen werden, ' + - 'dein Passwort preiszugeben. Um deine Bitcoins zu sichern, kann ' + - 'Veles Wallet einen weiteren verschlüsselten Speicher mit einem ' + - 'anderen Passwort erstellen. Unter Druck kannst du das ' + - 'zweite Passwort an Fremde weitergeben. Wenn eingegeben, öffnet ' + - 'Veles Wallet einen anderen Speicher zur Täuschung. Dies wirkt ' + - 'auf Fremde täuschend echt und dein Hauptspeicher bleibt geheim ' + - 'und sicher.', - help2: 'Der andere Speicher ist voll funktional und man kann einen Minimalbetrag für die Glaubhaftigkeit hinterlegen.', - create_fake_storage: 'Erstelle verschlüsselten Speicher zur Täuschung', - go_back: 'Zurück', - create_password: 'Erstelle ein Passwort', - create_password_explanation: 'Das Passwort für den täuschenden Speicher darf nicht mit dem deines Hauptspeichers übereinstimmen', - password_should_not_match: 'Das Passwort für den täuschenden Speicher darf nicht mit dem deines Hauptspeichers übereinstimmen', - retype_password: 'Passwort wiederholen', - passwords_do_not_match: 'Passwörter stimmen nicht überein. Neuer Versuch', - success: 'Erfolg!', + "Unter bestimmten Umständen könntest du dazu gezwungen werden, " + + "dein Passwort preiszugeben. Um deine Bitcoins zu sichern, kann " + + "Veles Wallet einen weiteren verschlüsselten Speicher mit einem " + + "anderen Passwort erstellen. Unter Druck kannst du das " + + "zweite Passwort an Fremde weitergeben. Wenn eingegeben, öffnet " + + "Veles Wallet einen anderen Speicher zur Täuschung. Dies wirkt " + + "auf Fremde täuschend echt und dein Hauptspeicher bleibt geheim " + + "und sicher.", + help2: + "Der andere Speicher ist voll funktional und man kann einen Minimalbetrag für die Glaubhaftigkeit hinterlegen.", + create_fake_storage: "Erstelle verschlüsselten Speicher zur Täuschung", + go_back: "Zurück", + create_password: "Erstelle ein Passwort", + create_password_explanation: + "Das Passwort für den täuschenden Speicher darf nicht mit dem deines Hauptspeichers übereinstimmen", + password_should_not_match: + "Das Passwort für den täuschenden Speicher darf nicht mit dem deines Hauptspeichers übereinstimmen", + retype_password: "Passwort wiederholen", + passwords_do_not_match: "Passwörter stimmen nicht überein. Neuer Versuch", + success: "Erfolg!" }, lnd: { - title: 'Beträge verwalten', - choose_source_wallet: 'Wähle eine Wallet als Zahlungsquelle', - refill_lnd_balance: 'Lade deine Lightning Wallet auf', - refill: 'Aufladen', - withdraw: 'Abheben', - placeholder: 'Invoice', + title: "Beträge verwalten", + choose_source_wallet: "Wähle eine Wallet als Zahlungsquelle", + refill_lnd_balance: "Lade deine Lightning Wallet auf", + refill: "Aufladen", + withdraw: "Abheben", + placeholder: "Invoice", sameWalletAsInvoiceError: - 'Du kannst nicht die Rechnung mit der Wallet begleichen, die du für die Erstellung dieser Rechnung verwendet hast.', + "Du kannst nicht die Rechnung mit der Wallet begleichen, die du für die Erstellung dieser Rechnung verwendet hast." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/el.js b/loc/el.js index aa56e64a56d..c924d03c228 100644 --- a/loc/el.js +++ b/loc/el.js @@ -1,246 +1,261 @@ module.exports = { _: { - storage_is_encrypted: 'Το αρχείο σου είναι κρυπτογραφημένο. Χρειάζεται ένας κωδικός για να αποκρυπτογραφηθεί.', - enter_password: 'Εισήγαγε κωδικό', - bad_password: 'Λάθος κωδικός, δοκίμασε ξανά', - never: 'ποτέ', - continue: 'Συνέχισε', - ok: 'Εντάξει', + storage_is_encrypted: + "Το αρχείο σου είναι κρυπτογραφημένο. Χρειάζεται ένας κωδικός για να αποκρυπτογραφηθεί.", + enter_password: "Εισήγαγε κωδικό", + bad_password: "Λάθος κωδικός, δοκίμασε ξανά", + never: "ποτέ", + continue: "Συνέχισε", + ok: "Εντάξει" }, wallets: { - select_wallet: 'Διάλεξε Πορτοφόλι', - options: 'επιλογές', + select_wallet: "Διάλεξε Πορτοφόλι", + options: "επιλογές", createBitcoinWallet: - 'Δεν έχεις πορτοφόλι Bitcoin. Για να βάλεις χρήματα στο πορτοφόλι Lightning, πρέπει πρώτα να δημιουργήσεις ή να εισάγεις ένα πορτοφόλι Bitcoin. Θα ήθελες να προχωρήσεις ούτως ή άλλως;', + "Δεν έχεις πορτοφόλι Bitcoin. Για να βάλεις χρήματα στο πορτοφόλι Lightning, πρέπει πρώτα να δημιουργήσεις ή να εισάγεις ένα πορτοφόλι Bitcoin. Θα ήθελες να προχωρήσεις ούτως ή άλλως;", list: { - app_name: 'Veles Wallet', - title: 'πορτοφόλια', + app_name: "Veles Wallet", + title: "πορτοφόλια", header: - 'Ένα πορτοφόλι αποτελείται από ένα μυστικό (το ιδιωτικό κλειδί) και μια διεύθυνση' + - 'την οποία μπορείς να δώσεις σε άλλους για να σε πληρώσουν σε αυτήν.', - add: 'Πρόσθεσε Πορτοφόλι', - create_a_wallet: 'Δημιούργησε ένα πορτοφόλι', - create_a_wallet1: 'Είναι δωρεάν και μπορείς να', - create_a_wallet2: 'δημιουργήσεις όσα θέλεις', - latest_transaction: 'τελευταία συναλλαγή', - empty_txs1: 'Οι συναλλαγές θα εμφανιστούν εδώ,', - empty_txs2: 'καμία συναλλαγή', + "Ένα πορτοφόλι αποτελείται από ένα μυστικό (το ιδιωτικό κλειδί) και μια διεύθυνση" + + "την οποία μπορείς να δώσεις σε άλλους για να σε πληρώσουν σε αυτήν.", + add: "Πρόσθεσε Πορτοφόλι", + create_a_wallet: "Δημιούργησε ένα πορτοφόλι", + create_a_wallet1: "Είναι δωρεάν και μπορείς να", + create_a_wallet2: "δημιουργήσεις όσα θέλεις", + latest_transaction: "τελευταία συναλλαγή", + empty_txs1: "Οι συναλλαγές θα εμφανιστούν εδώ,", + empty_txs2: "καμία συναλλαγή", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Πάτησε εδώ για να αγοράσεις Bitcoin', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Πάτησε εδώ για να αγοράσεις Bitcoin" }, reorder: { - title: 'Άλλαξε την σειρά των Πορτοφολιών', + title: "Άλλαξε την σειρά των Πορτοφολιών" }, add: { - title: 'Πρόσθεσε πορτοφόλι', + title: "Πρόσθεσε πορτοφόλι", description: - 'Μπορείς να σκανάρεις ένα χάρτινο πορτοφόλι (σε WIF - Wallet Import Format), ή να δημιουργήσεις ένα νέο πορτοφόλι. Υποστηρίζουμε πορτοφόλια τύπου Segwit.', - scan: 'Σκάναρε', - create: 'Δημιούργησε', - label_new_segwit: 'Νεό πορτοφόλι τύπου SegWit', - label_new_lightning: 'Νέο πορτοφόλι Lightning', - wallet_name: 'όνομα', - wallet_type: 'τύπος', - or: 'ή', - import_wallet: 'Εισήγαγε πορτοφόλι', - imported: 'Εισήχθηκε', - coming_soon: 'Σύντομα', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Μπορείς να σκανάρεις ένα χάρτινο πορτοφόλι (σε WIF - Wallet Import Format), ή να δημιουργήσεις ένα νέο πορτοφόλι. Υποστηρίζουμε πορτοφόλια τύπου Segwit.", + scan: "Σκάναρε", + create: "Δημιούργησε", + label_new_segwit: "Νεό πορτοφόλι τύπου SegWit", + label_new_lightning: "Νέο πορτοφόλι Lightning", + wallet_name: "όνομα", + wallet_type: "τύπος", + or: "ή", + import_wallet: "Εισήγαγε πορτοφόλι", + imported: "Εισήχθηκε", + coming_soon: "Σύντομα", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Πορτοφόλι', - address: 'Διεύθυνση', - type: 'Τύπος', - label: 'Ετικέτα', - destination: 'προορισμός', - description: 'περιγραφή', - are_you_sure: 'Είσαι σίγουρος;', - yes_delete: 'Ναι, διέγραψε', - no_cancel: 'Όχι, ακύρωσε', - delete: 'Διέγραψε', - save: 'Σώσε', - delete_this_wallet: 'Διέγραψε το πορτοφόλι', - export_backup: 'Εξήγαγε / δημιούργησε αντίγραφο ασφαλείας', - buy_bitcoin: 'Αγόρασε Bitcoin', - show_xpub: 'Δείξε το XPUB του πορτοφολιού', + title: "Πορτοφόλι", + address: "Διεύθυνση", + type: "Τύπος", + label: "Ετικέτα", + destination: "προορισμός", + description: "περιγραφή", + are_you_sure: "Είσαι σίγουρος;", + yes_delete: "Ναι, διέγραψε", + no_cancel: "Όχι, ακύρωσε", + delete: "Διέγραψε", + save: "Σώσε", + delete_this_wallet: "Διέγραψε το πορτοφόλι", + export_backup: "Εξήγαγε / δημιούργησε αντίγραφο ασφαλείας", + buy_bitcoin: "Αγόρασε Bitcoin", + show_xpub: "Δείξε το XPUB του πορτοφολιού" }, export: { - title: 'Εξαγωγή πορτοφολιού', + title: "Εξαγωγή πορτοφολιού" }, xpub: { - title: 'XPUB του πορτοφολιού', - copiedToClipboard: 'Αντιγράφηκε στο clipboard.', + title: "XPUB του πορτοφολιού", + copiedToClipboard: "Αντιγράφηκε στο clipboard." }, import: { - title: 'Εισαγωγή', + title: "Εισαγωγή", explanation: - 'Γράψε εδώ το μνημονικό (φράση), το ιδιωτικό κλειδί, το WIF, ή ό,τι άλλο έχεις. Το Veles Wallet θα προσπαθήσει να μαντέψει το σωστό format και να εισάγει το πορτοφόλι', - imported: 'Εισήχθη', - error: 'Η εισαγωγή απέτυχε. Παρακαλούμε σιγουρευτείτε ότι τα δεδομένα που εισάγετε είναι σωστά.', - success: 'Επιτυχία', - do_import: 'Εισήγαγε', - scan_qr: 'ή θέλεις θα σκανάρεις ένα QR code;', + "Γράψε εδώ το μνημονικό (φράση), το ιδιωτικό κλειδί, το WIF, ή ό,τι άλλο έχεις. Το Veles Wallet θα προσπαθήσει να μαντέψει το σωστό format και να εισάγει το πορτοφόλι", + imported: "Εισήχθη", + error: + "Η εισαγωγή απέτυχε. Παρακαλούμε σιγουρευτείτε ότι τα δεδομένα που εισάγετε είναι σωστά.", + success: "Επιτυχία", + do_import: "Εισήγαγε", + scan_qr: "ή θέλεις θα σκανάρεις ένα QR code;" }, scanQrWif: { - go_back: 'Πίσω', - cancel: 'Ακύρωσε', - decoding: 'Αποκωδικοποίηση', - input_password: 'Βάλε τον κωδικό', - password_explain: 'Αυτό είναι ένα κρυπτογραφημένο ιδιωτικό κλειδί τύπου BIP38', - bad_password: 'Λάθος κωδικός', - wallet_already_exists: 'Αυτό το πορτοφόλι υπάρχει ήδη', - bad_wif: 'Λάθος WIF', - imported_wif: 'Εισήχθη το WIF ', - with_address: ' με διεύθυνση ', - imported_segwit: 'Εισήχθη SegWit', - imported_legacy: 'Εισήχθη πορτοφόλιο παλαιού τύπου (Legacy)', - imported_watchonly: 'Εισήχθη πορτοφόλι παρακολούθησης (Watch-only)', - }, + go_back: "Πίσω", + cancel: "Ακύρωσε", + decoding: "Αποκωδικοποίηση", + input_password: "Βάλε τον κωδικό", + password_explain: + "Αυτό είναι ένα κρυπτογραφημένο ιδιωτικό κλειδί τύπου BIP38", + bad_password: "Λάθος κωδικός", + wallet_already_exists: "Αυτό το πορτοφόλι υπάρχει ήδη", + bad_wif: "Λάθος WIF", + imported_wif: "Εισήχθη το WIF ", + with_address: " με διεύθυνση ", + imported_segwit: "Εισήχθη SegWit", + imported_legacy: "Εισήχθη πορτοφόλιο παλαιού τύπου (Legacy)", + imported_watchonly: "Εισήχθη πορτοφόλι παρακολούθησης (Watch-only)" + } }, transactions: { list: { - tabBarLabel: 'Συναλλαγές', - title: 'συναλλαγές', - description: 'Λίστα των εισερχόμενων και εξερχόμενων συναλλαγών όλων των πορτοφολιών σου', - conf: 'conf', + tabBarLabel: "Συναλλαγές", + title: "συναλλαγές", + description: + "Λίστα των εισερχόμενων και εξερχόμενων συναλλαγών όλων των πορτοφολιών σου", + conf: "conf" }, details: { - title: 'Συναλλαγή', - from: 'Εισερχόμενες διευθύνσεις', - to: 'Εξερχόμενες διευθύνσεις', - copy: 'Αντέγραψε', - transaction_details: 'Λεπτομέρειες συναλλαγής', - show_in_block_explorer: 'Δείξε στον block explorer', - }, + title: "Συναλλαγή", + from: "Εισερχόμενες διευθύνσεις", + to: "Εξερχόμενες διευθύνσεις", + copy: "Αντέγραψε", + transaction_details: "Λεπτομέρειες συναλλαγής", + show_in_block_explorer: "Δείξε στον block explorer" + } }, send: { - header: 'Στείλε', + header: "Στείλε", details: { - title: 'δημιούργησε συναλλαγή', - amount_field_is_not_valid: 'Το ποσό δεν είναι σωστό', - fee_field_is_not_valid: 'Τα έξοδα συναλλαγής δεν είναι σωστά', - address_field_is_not_valid: 'Η διεύθυνση δεν είναι σωστή', - total_exceeds_balance: 'Δεν έχετε αρκετό υπόλοιπο για να στείλετε αυτό το ποσό.', - create_tx_error: 'Σφάλμα στην δημιουργία της συναλλαγής. Σιγουρευτείτε ότι η διεύθυνση είναι σωστή.', - address: 'διεύθυνση', - amount_placeholder: 'ποσό πληρωμής (σε VLS)', - fee_placeholder: 'συν έξοδα συναλλαγής (σε VLS)', - note_placeholder: 'Σημείωση', - cancel: 'Ακύρωση', - scan: 'Σκάναρε', - send: 'Στείλε', - create: 'Δημιούργησε', - remaining_balance: 'Υπόλοιπο', + title: "δημιούργησε συναλλαγή", + amount_field_is_not_valid: "Το ποσό δεν είναι σωστό", + fee_field_is_not_valid: "Τα έξοδα συναλλαγής δεν είναι σωστά", + address_field_is_not_valid: "Η διεύθυνση δεν είναι σωστή", + total_exceeds_balance: + "Δεν έχετε αρκετό υπόλοιπο για να στείλετε αυτό το ποσό.", + create_tx_error: + "Σφάλμα στην δημιουργία της συναλλαγής. Σιγουρευτείτε ότι η διεύθυνση είναι σωστή.", + address: "διεύθυνση", + amount_placeholder: "ποσό πληρωμής (σε VLS)", + fee_placeholder: "συν έξοδα συναλλαγής (σε VLS)", + note_placeholder: "Σημείωση", + cancel: "Ακύρωση", + scan: "Σκάναρε", + send: "Στείλε", + create: "Δημιούργησε", + remaining_balance: "Υπόλοιπο" }, confirm: { - header: 'Επικύρωση', - sendNow: 'Στείλε τώρα', + header: "Επικύρωση", + sendNow: "Στείλε τώρα" }, success: { - done: 'Ολοκληρώθηκε', + done: "Ολοκληρώθηκε" }, create: { - details: 'Λεπτομέρειες', - title: 'δημιούργησε συναλλαγή', - error: 'Σφάλμα στη δημιουργία συναλλαγής. Λάθος διεύθυνση ή ποσό συναλλαγής;', - go_back: 'Πίσω', - this_is_hex: 'Αυτή είναι η υπογεγραμμένη συναλλαγή σε μορφή hex και είναι έτοιμη για αποστολή στο δίκτυο.', - to: 'Προς', - amount: 'Ποσό', - fee: 'Έξοδα', - tx_size: 'Μέγεθος συναλλαγής', - satoshi_per_byte: 'Satoshi ανά byte', - memo: 'Σημείωση', - broadcast: 'Στείλε στο δίκτυο', - not_enough_fee: 'Τα έξοδα συναλλαγής δεν είναι αρκετά. Αυξήστε τα.', - }, + details: "Λεπτομέρειες", + title: "δημιούργησε συναλλαγή", + error: + "Σφάλμα στη δημιουργία συναλλαγής. Λάθος διεύθυνση ή ποσό συναλλαγής;", + go_back: "Πίσω", + this_is_hex: + "Αυτή είναι η υπογεγραμμένη συναλλαγή σε μορφή hex και είναι έτοιμη για αποστολή στο δίκτυο.", + to: "Προς", + amount: "Ποσό", + fee: "Έξοδα", + tx_size: "Μέγεθος συναλλαγής", + satoshi_per_byte: "Satoshi ανά byte", + memo: "Σημείωση", + broadcast: "Στείλε στο δίκτυο", + not_enough_fee: "Τα έξοδα συναλλαγής δεν είναι αρκετά. Αυξήστε τα." + } }, receive: { - header: 'Λήψη', + header: "Λήψη", details: { - title: 'Δώσε αυτήν τη διεύθυνση στον πληρωτή', - share: 'Δώσε', - copiedToClipboard: 'Αντιγράφηκε στο clipboard.', - label: 'Περιγραφή', - create: 'Δημιούργησε', - setAmount: 'Λάβε με ποσό', + title: "Δώσε αυτήν τη διεύθυνση στον πληρωτή", + share: "Δώσε", + copiedToClipboard: "Αντιγράφηκε στο clipboard.", + label: "Περιγραφή", + create: "Δημιούργησε", + setAmount: "Λάβε με ποσό" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Αγόρασε Bitcoin', - tap_your_address: 'Πάτησε στην διεύθυνσή σου για να αντιγραφεί στο clipboard:', - copied: 'Αντιγράφηκε στο Clipboard!', + header: "Αγόρασε Bitcoin", + tap_your_address: + "Πάτησε στην διεύθυνσή σου για να αντιγραφεί στο clipboard:", + copied: "Αντιγράφηκε στο Clipboard!" }, settings: { - header: 'ρυθμίσεις', - plausible_deniability: 'Εύλογη δυνατότητα άρνησης...', - storage_not_encrypted: 'Το αρχείο δεν είναι κρυπτογραφημένο', - storage_encrypted: 'Το αρχείο είναι κρυπτογραφημένο', - password: 'Κωδικός', - password_explain: 'Δώσε ένα κωδικό για την κρυπτογράφηση του αρχείου', - retype_password: 'Ξαναδώσε τον κωδικό', - passwords_do_not_match: 'Οι κωδικοί δεν είναι ίδιοι', - encrypt_storage: 'Κρυπτογράφησε το αρχείο', - lightning_settings: 'Ρυθμίσεις Lightning', + header: "ρυθμίσεις", + plausible_deniability: "Εύλογη δυνατότητα άρνησης...", + storage_not_encrypted: "Το αρχείο δεν είναι κρυπτογραφημένο", + storage_encrypted: "Το αρχείο είναι κρυπτογραφημένο", + password: "Κωδικός", + password_explain: "Δώσε ένα κωδικό για την κρυπτογράφηση του αρχείου", + retype_password: "Ξαναδώσε τον κωδικό", + passwords_do_not_match: "Οι κωδικοί δεν είναι ίδιοι", + encrypt_storage: "Κρυπτογράφησε το αρχείο", + lightning_settings: "Ρυθμίσεις Lightning", lightning_settings_explain: - 'Για να συνδεθείτε στον δικό σας κόμβο LND παρακαλούμε εγκαταστήστε το LndHub' + - ' και βάλτε το URL του εδώ. Αφήστε το κενό για να χρησιμοποιήσετε το LNDHub της Veles Wallet (lndhub.io). Αφού σώσετε τις ρυθμίσεις τυχόν νέα πορτοφόλια που θα δημιουργήσετε θα συνδεθούν στο LNDHub που επιλέξατε.', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Σώσε', - about: 'Σχετικά', - language: 'Γλώσσα', - currency: 'Νόμισμα', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Για να συνδεθείτε στον δικό σας κόμβο LND παρακαλούμε εγκαταστήστε το LndHub" + + " και βάλτε το URL του εδώ. Αφήστε το κενό για να χρησιμοποιήσετε το LNDHub της Veles Wallet (lndhub.io). Αφού σώσετε τις ρυθμίσεις τυχόν νέα πορτοφόλια που θα δημιουργήσετε θα συνδεθούν στο LNDHub που επιλέξατε.", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Σώσε", + about: "Σχετικά", + language: "Γλώσσα", + currency: "Νόμισμα", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Εύλογη δυνατότητα άρνησης', + title: "Εύλογη δυνατότητα άρνησης", help: - 'Μπορεί κάποια στιγμή να υποχρεωθείτε να αποκαλύψετε τον ' + - 'κωδικό σας. Για να προστατέψετε τα χρήματά σας, το Veles Wallet μπορεί να δημιουργήσει ένα εναλλακτικό ' + - 'κρυπτογραφημένο αρχείο με διαφορετικό κωδικό. Εάν σας υποχρεώσουν, ' + - 'μπορείτε να αποκαλύψετε αυτόν τον δεύτερο κωδικό. Κάποιος που θα τον ' + - 'βάλει στο Veles Wallet θα δει ένα μόνο ένα ψεύτικο αρχείο που μοιάζει ' + - 'κανονικό, προστατεύοντας έτσι το κανονικό σας αρχείο και ' + - 'τα χρήματά σας.', - help2: 'Το νέο αρχείο θα είναι πλήρως λειτουργικό, και μπορείτε να βάλετε εκεί ' + 'κάποια ελάχιστα χρήματα για να μοιάζει αληθινό.', - create_fake_storage: 'Δημιούργησε ένα ψεύτικο κρυπτογραφημένο αρχείο', - go_back: 'Πίσω', - create_password: 'Δώσε έναν κωδικό', - create_password_explanation: 'Ο κωδικός του ψεύτικου αρχείου δεν πρέπει να είναι ίδιος με τον κωδικό του πραγματικού αρχείου', - password_should_not_match: 'Ο κωδικός του ψεύτικου αρχείου δεν πρέπει να είναι ίδιος με τον κωδικό του πραγματικού αρχείου', - retype_password: 'Ξαναδώσε τον κωδικό', - passwords_do_not_match: 'Οι κωδικοί δεν είναι ίδιοι, δοκίμασε ξανά', - success: 'Επιτυχία', + "Μπορεί κάποια στιγμή να υποχρεωθείτε να αποκαλύψετε τον " + + "κωδικό σας. Για να προστατέψετε τα χρήματά σας, το Veles Wallet μπορεί να δημιουργήσει ένα εναλλακτικό " + + "κρυπτογραφημένο αρχείο με διαφορετικό κωδικό. Εάν σας υποχρεώσουν, " + + "μπορείτε να αποκαλύψετε αυτόν τον δεύτερο κωδικό. Κάποιος που θα τον " + + "βάλει στο Veles Wallet θα δει ένα μόνο ένα ψεύτικο αρχείο που μοιάζει " + + "κανονικό, προστατεύοντας έτσι το κανονικό σας αρχείο και " + + "τα χρήματά σας.", + help2: + "Το νέο αρχείο θα είναι πλήρως λειτουργικό, και μπορείτε να βάλετε εκεί " + + "κάποια ελάχιστα χρήματα για να μοιάζει αληθινό.", + create_fake_storage: "Δημιούργησε ένα ψεύτικο κρυπτογραφημένο αρχείο", + go_back: "Πίσω", + create_password: "Δώσε έναν κωδικό", + create_password_explanation: + "Ο κωδικός του ψεύτικου αρχείου δεν πρέπει να είναι ίδιος με τον κωδικό του πραγματικού αρχείου", + password_should_not_match: + "Ο κωδικός του ψεύτικου αρχείου δεν πρέπει να είναι ίδιος με τον κωδικό του πραγματικού αρχείου", + retype_password: "Ξαναδώσε τον κωδικό", + passwords_do_not_match: "Οι κωδικοί δεν είναι ίδιοι, δοκίμασε ξανά", + success: "Επιτυχία" }, lnd: { - title: 'Διαχείριση χρημάτων', - choose_source_wallet: 'Διάλεξε ένα πορτοφόλι', - refill_lnd_balance: 'Γέμισε το πορτοφόλι Lightning', - refill: 'Γέμισμα πορτοφολιού', - withdraw: 'Ανάληψη', - expired: 'Έληξε', - placeholder: 'Τιμολόγιο', - sameWalletAsInvoiceError: 'Δεν μπορείς να εξοφλήσεις ένα τιμολόγιο από το ίδιο πορτοφόλι με το οποίο δημιουργήθηκε.', + title: "Διαχείριση χρημάτων", + choose_source_wallet: "Διάλεξε ένα πορτοφόλι", + refill_lnd_balance: "Γέμισε το πορτοφόλι Lightning", + refill: "Γέμισμα πορτοφολιού", + withdraw: "Ανάληψη", + expired: "Έληξε", + placeholder: "Τιμολόγιο", + sameWalletAsInvoiceError: + "Δεν μπορείς να εξοφλήσεις ένα τιμολόγιο από το ίδιο πορτοφόλι με το οποίο δημιουργήθηκε." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/en.js b/loc/en.js index 5508c42b7bd..960ad0cbc6e 100644 --- a/loc/en.js +++ b/loc/en.js @@ -1,21 +1,24 @@ module.exports = { _: { - storage_is_encrypted: "Your storage is encrypted. Password is required to decrypt it", + storage_is_encrypted: + "Your storage is encrypted. Password is required to decrypt it", enter_password: "Enter password", bad_password: "Bad password, try again", never: "never", continue: "Continue", - ok: "OK", + ok: "OK" }, wallets: { overview_wallets: "Overview", select_wallet: "Select Wallet", options: "options", - createBitcoinWallet: "You currently do not have a Bitcoin wallet. In order to fund a Lightning wallet, a Bitcoin wallet needs to be created or imported. Would you like to continue anyway?", + createBitcoinWallet: + "You currently do not have a Bitcoin wallet. In order to fund a Lightning wallet, a Bitcoin wallet needs to be created or imported. Would you like to continue anyway?", list: { - app_name: "Veles Wallet", + app_name: "Veles Wallet", title: "wallets", - header: "A wallet represents a pair of a secret (private key) and an address you can share to receive coins.", + header: + "A wallet represents a pair of a secret (private key) and an address you can share to receive coins.", add: "Add Wallet", create_a_wallet: "Create a wallet", create_a_wallet1: "It's free and you can create", @@ -23,16 +26,19 @@ module.exports = { latest_transaction: "latest transaction", empty_txs1: "Your transactions will appear here,", empty_txs2: "none at the moment", - empty_txs1_lightning: "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", - empty_txs2_lightning: "\nTo start using it tap on \"manage funds\" and topup your balance.", - tap_here_to_buy: "Tap here to buy Bitcoin", + empty_txs1_lightning: + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Tap here to buy Bitcoin" }, reorder: { - title: "Reorder Wallets", + title: "Reorder Wallets" }, add: { title: "add wallet", - description: "You can either scan backup paper wallet (in WIF - Wallet Import Format), or create a new wallet. Segwit wallets supported by default.", + description: + "You can either scan backup paper wallet (in WIF - Wallet Import Format), or create a new wallet. Segwit wallets supported by default.", scan: "Scan", create: "Create", label_new_segwit: "New SegWit", @@ -44,7 +50,7 @@ module.exports = { imported: "Imported", coming_soon: "Coming soon", lightning: "Lightning", - bitcoin: "Veles", + bitcoin: "Veles" }, details: { title: "Wallet", @@ -62,23 +68,25 @@ module.exports = { export_backup: "Export / backup", buy_bitcoin: "Buy Bitcoin", show_xpub: "Show wallet XPUB", - mnemoic_seed: "Mnemoic Seed", + mnemoic_seed: "Mnemoic Seed" }, export: { - title: "wallet export", + title: "wallet export" }, xpub: { title: "wallet XPUB", - copiedToClipboard: "Copied to clipboard.", + copiedToClipboard: "Copied to clipboard." }, import: { title: "import", - explanation: "Write here your mnemonic, private key, WIF, or anything you've got. Veles Wallet will do its best to guess the correct format and import your wallet", + explanation: + "Write here your mnemonic, private key, WIF, or anything you've got. Veles Wallet will do its best to guess the correct format and import your wallet", imported: "Imported", - error: "Failed to import. Please, make sure that the provided data is valid.", + error: + "Failed to import. Please, make sure that the provided data is valid.", success: "Success", do_import: "Import", - scan_qr: "or scan QR code instead?", + scan_qr: "or scan QR code instead?" }, scanQrWif: { go_back: "Go Back", @@ -93,15 +101,15 @@ module.exports = { with_address: "with address", imported_segwit: "Imported SegWit", imported_legacy: "Imported Legacy", - imported_watchonly: "Imported Watch-only", - }, + imported_watchonly: "Imported Watch-only" + } }, transactions: { list: { tabBarLabel: "Transactions", title: "transactions", description: "A list of ingoing or outgoing transactions of your wallets", - conf: "conf", + conf: "conf" }, details: { title: "Transaction", @@ -109,20 +117,21 @@ module.exports = { to: "To", copy: "Copy", transaction_details: "Transaction details", - show_in_block_explorer: "View in block explorer", - }, + show_in_block_explorer: "View in block explorer" + } }, send: { header: "Send", success: { - done: "Done", + done: "Done" }, details: { title: "create transaction", amount_field_is_not_valid: "Amount field is not valid", fee_field_is_not_valid: "Fee field is not valid", address_field_is_not_valid: "Address field is not valid", - create_tx_error: "There was an error creating the transaction. Please, make sure the address is valid.", + create_tx_error: + "There was an error creating the transaction. Please, make sure the address is valid.", address: "address", amount_placeholder: "amount to send (in VLS)", fee_placeholder: "plus transaction fee (in VLS)", @@ -132,18 +141,19 @@ module.exports = { send: "Send", create: "Create Invoice", remaining_balance: "Remaining balance", - total_exceeds_balance: "The sending amount exceeds the available balance.", + total_exceeds_balance: "The sending amount exceeds the available balance." }, confirm: { header: "Confirm", - sendNow: "Send now", + sendNow: "Send now" }, create: { details: "Details", title: "create transaction", error: "Error creating transaction. Invalid address or send amount?", go_back: "Go Back", - this_is_hex: "This is transaction hex, signed and ready to be broadcast to the network.", + this_is_hex: + "This is transaction hex, signed and ready to be broadcast to the network.", to: "To", amount: "Amount", fee: "Fee", @@ -151,8 +161,8 @@ module.exports = { satoshi_per_byte: "Satoshi per byte", memo: "Memo", broadcast: "Broadcast", - not_enough_fee: "Not enough fee. Increase the fee", - }, + not_enough_fee: "Not enough fee. Increase the fee" + } }, receive: { header: "Receive", @@ -162,14 +172,14 @@ module.exports = { copiedToClipboard: "Copied to clipboard.", label: "Description", create: "Create", - setAmount: "Receive with amount", + setAmount: "Receive with amount" }, - scan_lnurl: "Scan to receive", + scan_lnurl: "Scan to receive" }, buyBitcoin: { header: "Buy Bitcoin", tap_your_address: "Tap your address to copy it to clipboard", - copied: "Copied to Clipboard!", + copied: "Copied to Clipboard!" }, settings: { header: "settings", @@ -189,20 +199,24 @@ module.exports = { language: "Language", currency: "Currency", advanced_options: "Advanced Options", - enable_advanced_mode: "Enable advanced mode", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { title: "Plausible Deniability", - help: "Under certain circumstances, you might be forced to disclose a password. To keep your coins safe, Veles Wallet can create another encrypted storage, with a different password. Under pressure, you can disclose this password to a 3rd party. If entered in Veles Wallet, it will unlock new fake storage. This will seem legit to a 3rd party, but will secretly keep your main storage with coins safe.", - help2: "New storage will be fully functional, and you can store some minimum amounts there so it looks more believable.", + help: + "Under certain circumstances, you might be forced to disclose a password. To keep your coins safe, Veles Wallet can create another encrypted storage, with a different password. Under pressure, you can disclose this password to a 3rd party. If entered in Veles Wallet, it will unlock new fake storage. This will seem legit to a 3rd party, but will secretly keep your main storage with coins safe.", + help2: + "New storage will be fully functional, and you can store some minimum amounts there so it looks more believable.", create_fake_storage: "Create fake encrypted storage", go_back: "Go Back", create_password: "Create a password", - create_password_explanation: "Password for fake storage should not match password for your main storage", - password_should_not_match: "Password for fake storage should not match password for your main storage", + create_password_explanation: + "Password for fake storage should not match password for your main storage", + password_should_not_match: + "Password for fake storage should not match password for your main storage", retype_password: "Retype password", passwords_do_not_match: "Passwords do not match, try again", - success: "Success", + success: "Success" }, lnd: { title: "manage funds", @@ -212,12 +226,14 @@ module.exports = { withdraw: "Withdraw", placeholder: "Invoice", expired: "Expired", - sameWalletAsInvoiceError: "You can not pay an invoice with the same wallet used to create it.", + sameWalletAsInvoiceError: + "You can not pay an invoice with the same wallet used to create it." }, pleasebackup: { title: "Your wallet is created...", - text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: "OK, I wrote this down!", + text: + "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", + ok: "OK, I wrote this down!" }, lndViewInvoice: { wasnt_paid_and_expired: "This invoice was not paid for and has expired", @@ -226,6 +242,6 @@ module.exports = { sats: "sats", for: "For", additional_info: "Additional Information", - open_direct_channel: "Open direct channel with this node", - }, + open_direct_channel: "Open direct channel with this node" + } }; diff --git a/loc/es.js b/loc/es.js index 1787c8ad16c..d7fb4e76b1c 100644 --- a/loc/es.js +++ b/loc/es.js @@ -1,20 +1,23 @@ module.exports = { _: { - storage_is_encrypted: "Su almacenamiento está cifrado. Se requiere contraseña para descifrarlo.", + storage_is_encrypted: + "Su almacenamiento está cifrado. Se requiere contraseña para descifrarlo.", enter_password: "Introduzca la contraseña", bad_password: "Contraseña incorrecta. Intente nuevamente.", never: "nunca", continue: "Continuar", - ok: "OK", + ok: "OK" }, wallets: { options: "Seleccionar cartera", select_wallet: "opciones", - createBitcoinWallet: "En este momento no tiene ninguna cartera de bitcóin. Para financiar una cartera lightning, se debe crear o importar una cartera de bitcóin. ¿Quiere continuar de todos modos?", + createBitcoinWallet: + "En este momento no tiene ninguna cartera de bitcóin. Para financiar una cartera lightning, se debe crear o importar una cartera de bitcóin. ¿Quiere continuar de todos modos?", list: { app_name: "Veles Wallet", title: "carteras", - header: "Un cartera representa un par de secretos (clave privada) y una dirección que puede compartir para recibir monedas.", + header: + "Un cartera representa un par de secretos (clave privada) y una dirección que puede compartir para recibir monedas.", add: "Añadir cartera", create_a_wallet: "Crear una cartera", create_a_wallet1: "Es gratis y puede crear tantas", @@ -22,16 +25,19 @@ module.exports = { latest_transaction: "última transacción", empty_txs1: "Sus transacciones aparecerán aquí,", empty_txs2: "por el momento no hay ninguna", - empty_txs1_lightning: "La cartera lightning se debe usar para sus transacciones diarias. Las tarifas son injustamente baratas y la velocidad es increíblemente rápida.", - empty_txs2_lightning: "\nPara comenzar a usarla, toque en \"gestionar fondos\" y cargue su saldo.", - tap_here_to_buy: "Toque aquí para comprar bitcoines", + empty_txs1_lightning: + "La cartera lightning se debe usar para sus transacciones diarias. Las tarifas son injustamente baratas y la velocidad es increíblemente rápida.", + empty_txs2_lightning: + '\nPara comenzar a usarla, toque en "gestionar fondos" y cargue su saldo.', + tap_here_to_buy: "Toque aquí para comprar bitcoines" }, reorder: { - title: "Reorganizar cartera", + title: "Reorganizar cartera" }, add: { title: "Añadir cartera", - description: "Puede escanear la cartera de papel de respaldo (en WIF, formato de importación de carteras) o crear una nueva cartera. Las carteras SegWit son compatibles por defecto.", + description: + "Puede escanear la cartera de papel de respaldo (en WIF, formato de importación de carteras) o crear una nueva cartera. Las carteras SegWit son compatibles por defecto.", scan: "Escanear", create: "Crear", label_new_segwit: "Nuevo SegWit", @@ -43,7 +49,7 @@ module.exports = { imported: "Importado", coming_soon: "Viene pronto", lightning: "Lightning", - bitcoin: "Veles", + bitcoin: "Veles" }, details: { title: "Cartera", @@ -60,23 +66,25 @@ module.exports = { delete_this_wallet: "Eliminar esta cartera", export_backup: "Exportar/guardar", buy_bitcoin: "Comprar bitcóines", - show_xpub: "Mostrar cartera XPUB", + show_xpub: "Mostrar cartera XPUB" }, export: { - title: "exportación de cartera", + title: "exportación de cartera" }, xpub: { title: "cartera XPUB", - copiedToClipboard: "Copiado a portapapeles.", + copiedToClipboard: "Copiado a portapapeles." }, import: { title: "importar", - explanation: "Escriba aquí su clave mnemotécnica, clave privada, WIF o cualquier cosa que tenga. Veles Wallet hará todo lo posible para adivinar el formato correcto e importar su cartera.", + explanation: + "Escriba aquí su clave mnemotécnica, clave privada, WIF o cualquier cosa que tenga. Veles Wallet hará todo lo posible para adivinar el formato correcto e importar su cartera.", imported: "Importado", - error: "No se ha podido importar. Asegúrese de que los datos que ha proporcionado son válidos.", + error: + "No se ha podido importar. Asegúrese de que los datos que ha proporcionado son válidos.", success: "Éxito", do_import: "Importar", - scan_qr: "¿o escanear codigo QR?", + scan_qr: "¿o escanear codigo QR?" }, scanQrWif: { go_back: "Regresar", @@ -91,15 +99,16 @@ module.exports = { with_address: "con dirección", imported_segwit: "SegWit importado", imported_legacy: "Legado importado", - imported_watchonly: "Solo-lectura importado", - }, + imported_watchonly: "Solo-lectura importado" + } }, transactions: { list: { tabBarLabel: "Transacciones", title: "transacciones", - description: "Una lista de las transacciones entrantes o salientes de sus carteras", - conf: "conf", + description: + "Una lista de las transacciones entrantes o salientes de sus carteras", + conf: "conf" }, details: { title: "Transaccion", @@ -107,20 +116,21 @@ module.exports = { to: "A", copy: "Copiar", transaction_details: "Detalles de la transacción", - show_in_block_explorer: "Mostrar en explorador de bloques", - }, + show_in_block_explorer: "Mostrar en explorador de bloques" + } }, send: { header: "Enviar", success: { - done: "Hecho", + done: "Hecho" }, details: { title: "crear transacción", amount_field_is_not_valid: "La cantidad no es válida", fee_field_is_not_valid: "La tasa no es válida", address_field_is_not_valid: "La dirección no es válida", - create_tx_error: "Se ha producido un error al crear la transacción. Por favor, asegúrese de que la dirección es válida.", + create_tx_error: + "Se ha producido un error al crear la transacción. Por favor, asegúrese de que la dirección es válida.", address: "dirección", amount_placeholder: "cantidad a enviar (en VLS)", fee_placeholder: "más tasa de transaccion (en VLS)", @@ -130,18 +140,20 @@ module.exports = { send: "Enviar", create: "Crear factura", remaining_balance: "Saldo restante", - total_exceeds_balance: "El monto de envío excede el saldo disponible.", + total_exceeds_balance: "El monto de envío excede el saldo disponible." }, confirm: { header: "Confirmar", - sendNow: "Enviar ahora", + sendNow: "Enviar ahora" }, create: { title: "Detalles", details: "crear transacción", - error: "Error al crear la transacción. ¿La dirección o cantidad son invalidas?", + error: + "Error al crear la transacción. ¿La dirección o cantidad son invalidas?", go_back: "Regresar", - this_is_hex: "Esta es una transacción hexadecimal, firmada y lista para ser transmitida a la red.", + this_is_hex: + "Esta es una transacción hexadecimal, firmada y lista para ser transmitida a la red.", to: "A", amount: "Cantidad", fee: "Tasa", @@ -149,8 +161,8 @@ module.exports = { satoshi_per_byte: "Satoshi por byte", memo: "Comentario", broadcast: "Transmitir", - not_enough_fee: "Tasa no suficiente. Incremente la tasa", - }, + not_enough_fee: "Tasa no suficiente. Incremente la tasa" + } }, receive: { header: "Recibir", @@ -160,14 +172,14 @@ module.exports = { copiedToClipboard: "Copiado a portapapeles.", label: "Descripción", create: "Crear", - setAmount: "Recibir con cantidad", + setAmount: "Recibir con cantidad" }, - scan_lnurl: "Escanear para recibir", + scan_lnurl: "Escanear para recibir" }, buyBitcoin: { header: "Comprar bitcoines", tap_your_address: "Toque su dirección para copiarla al portapapeles", - copied: "¡Copiada al portapapeles!", + copied: "¡Copiada al portapapeles!" }, settings: { header: "ajustes", @@ -175,7 +187,8 @@ module.exports = { storage_not_encrypted: "Almacenamiento no cifrado", storage_encrypted: "Almacenamiento cifrado", password: "Contraseña", - password_explain: "Cree la contraseña que usará para descifrar el almacenamiento", + password_explain: + "Cree la contraseña que usará para descifrar el almacenamiento", retype_password: "Introduzca la contraseña nuevamente", passwords_do_not_match: "Las contraseñas no coinciden", encrypt_storage: "Cifrar almacenamiento", @@ -187,20 +200,24 @@ module.exports = { language: "Idioma", currency: "Moneda", advanced_options: "Opciones avanzadas", - enable_advanced_mode: "Habilitar modo avanzado", + enable_advanced_mode: "Habilitar modo avanzado" }, plausibledeniability: { title: "Negación plausible", - help: "En determinadas circunstancias, podría verse obligado a revelar su contraseña. Para mantener sus monedas seguras, Veles Wallet puede crear otro almacenamiento cifrado con una contraseña diferente. Bajo presión, podría revelar esta contraseña a un tercero. Si se ingresa en Veles Wallet, desbloqueará un nuevo almacenamiento falso. Esto parecerá legítimo para un tercero, pero mantendrá en secreto su almacenamiento principal con monedas.", - help2: "El nuevo almacenamiento será completamente funcional, y puede almacenar cantidades mínimas para que sea mas creíble.", + help: + "En determinadas circunstancias, podría verse obligado a revelar su contraseña. Para mantener sus monedas seguras, Veles Wallet puede crear otro almacenamiento cifrado con una contraseña diferente. Bajo presión, podría revelar esta contraseña a un tercero. Si se ingresa en Veles Wallet, desbloqueará un nuevo almacenamiento falso. Esto parecerá legítimo para un tercero, pero mantendrá en secreto su almacenamiento principal con monedas.", + help2: + "El nuevo almacenamiento será completamente funcional, y puede almacenar cantidades mínimas para que sea mas creíble.", create_fake_storage: "Crear un almacen cifrado falso", go_back: "Regresar", create_password: "Crear una contraseña", - create_password_explanation: "La contraseña para el almacenamiento falso no puede ser la misma que para su almacen principal.", - password_should_not_match: "La contraseña para el almacenamiento falso no puede ser la misma que para su almacen principal.", + create_password_explanation: + "La contraseña para el almacenamiento falso no puede ser la misma que para su almacen principal.", + password_should_not_match: + "La contraseña para el almacenamiento falso no puede ser la misma que para su almacen principal.", retype_password: "Volver a escribir la contraseña", passwords_do_not_match: "Las contraseñas no coinciden, intente nuevamente", - success: "Éxito", + success: "Éxito" }, lnd: { title: "gestionar fondos", @@ -210,12 +227,14 @@ module.exports = { withdraw: "Retirar", placeholder: "Factura", expired: "Expirado", - sameWalletAsInvoiceError: "No puede pagar una factura con la misma cartera utilizada para crearla.", + sameWalletAsInvoiceError: + "No puede pagar una factura con la misma cartera utilizada para crearla." }, pleasebackup: { title: "Se ha creado su cartera…", - text: "Tómese un momento para escribir esta frase mnemónica en una hoja de papel. Es su copia de seguridad que puede usar para restaurar la cartera en otro dispositivo.", - ok: "¡OK, la he apuntado!", + text: + "Tómese un momento para escribir esta frase mnemónica en una hoja de papel. Es su copia de seguridad que puede usar para restaurar la cartera en otro dispositivo.", + ok: "¡OK, la he apuntado!" }, lndViewInvoice: { wasnt_paid_and_expired: "Esfa factura no ha sido pagada y ha expirado", @@ -224,6 +243,6 @@ module.exports = { sats: "sats", for: "Para", additional_info: "Información adicional", - open_direct_channel: "Abrir canal directo con este nodo", - }, + open_direct_channel: "Abrir canal directo con este nodo" + } }; diff --git a/loc/fi_FI.js b/loc/fi_FI.js index d5c378a4bb8..d42755b3bf8 100644 --- a/loc/fi_FI.js +++ b/loc/fi_FI.js @@ -1,246 +1,256 @@ module.exports = { _: { - storage_is_encrypted: 'Tallennustilasi on salattu. Salasana vaaditaan sen purkamiseksi', - enter_password: 'Anna salasana', - bad_password: 'Väärä salasana, yritä uudelleen', - never: 'ei koskaan', - continue: 'Jatka', - ok: 'OK', + storage_is_encrypted: + "Tallennustilasi on salattu. Salasana vaaditaan sen purkamiseksi", + enter_password: "Anna salasana", + bad_password: "Väärä salasana, yritä uudelleen", + never: "ei koskaan", + continue: "Jatka", + ok: "OK" }, wallets: { - select_wallet: 'Valitse Lompakko', - options: 'valinnat', + select_wallet: "Valitse Lompakko", + options: "valinnat", createBitcoinWallet: - 'Sinulla ei tällä hetkellä ole Bitcoin lompakkoa. Rahoittaaksesi Lightning lompakkoa, Bitcoin lompakko tulee tuoda tai luoda. Haluatko kuitenkin jatkaa?', + "Sinulla ei tällä hetkellä ole Bitcoin lompakkoa. Rahoittaaksesi Lightning lompakkoa, Bitcoin lompakko tulee tuoda tai luoda. Haluatko kuitenkin jatkaa?", list: { - app_name: 'Veles Wallet', - title: 'lompakot', + app_name: "Veles Wallet", + title: "lompakot", header: - 'Lompakko koostuu salaisesta avaimesta (private key) sekä julkisesta osoitteesta' + - ',jonka voit jakaa vastaanottaaksesi kolikoita.', - add: 'Lisää Lompakko', - create_a_wallet: 'Luo lompakko', - create_a_wallet1: 'Se on ilmaista ja voit luoda', - create_a_wallet2: 'niin monta kuin haluat', - latest_transaction: 'viimeisin siirto', - empty_txs1: 'Siirtosi näkyvät tässä,', - empty_txs2: 'ei siirtoja', + "Lompakko koostuu salaisesta avaimesta (private key) sekä julkisesta osoitteesta" + + ",jonka voit jakaa vastaanottaaksesi kolikoita.", + add: "Lisää Lompakko", + create_a_wallet: "Luo lompakko", + create_a_wallet1: "Se on ilmaista ja voit luoda", + create_a_wallet2: "niin monta kuin haluat", + latest_transaction: "viimeisin siirto", + empty_txs1: "Siirtosi näkyvät tässä,", + empty_txs2: "ei siirtoja", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Napsauta tästä ostaaksesi Bitcoinia', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Napsauta tästä ostaaksesi Bitcoinia" }, reorder: { - title: 'Järjestele Lompakot', + title: "Järjestele Lompakot" }, add: { - title: 'lisää lompakko', + title: "lisää lompakko", description: - 'Voit joko skannata paperisen lompakon (WIF - Wallet Import Format), tai luoda uuden. Segwit lompakkoja tuetaan oletuksena.', - scan: 'Skannaa', - create: 'Luo', - label_new_segwit: 'Uusi SegWit', - label_new_lightning: 'Uusi Lightning', - wallet_name: 'nimi', - wallet_type: 'tyyppi', - or: 'tai', - import_wallet: 'Tuo lompakko', - imported: 'Tuotu', - coming_soon: 'Tulossa', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Voit joko skannata paperisen lompakon (WIF - Wallet Import Format), tai luoda uuden. Segwit lompakkoja tuetaan oletuksena.", + scan: "Skannaa", + create: "Luo", + label_new_segwit: "Uusi SegWit", + label_new_lightning: "Uusi Lightning", + wallet_name: "nimi", + wallet_type: "tyyppi", + or: "tai", + import_wallet: "Tuo lompakko", + imported: "Tuotu", + coming_soon: "Tulossa", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Lompakko', - address: 'Osoite', - type: 'Tyyppi', - label: 'Etiketti', - destination: 'määränpää', - description: 'kuvaus', - are_you_sure: 'Oletko varma?', - yes_delete: 'Kyllä, poista', - no_cancel: 'En, peruuta', - delete: 'Poista', - save: 'Tallenna', - delete_this_wallet: 'Poista tämä lompakko', - export_backup: 'Vie / varmuuskopioi', - buy_bitcoin: 'Osta Bitcoinia', - show_xpub: 'Näytä lompakon XPUB', + title: "Lompakko", + address: "Osoite", + type: "Tyyppi", + label: "Etiketti", + destination: "määränpää", + description: "kuvaus", + are_you_sure: "Oletko varma?", + yes_delete: "Kyllä, poista", + no_cancel: "En, peruuta", + delete: "Poista", + save: "Tallenna", + delete_this_wallet: "Poista tämä lompakko", + export_backup: "Vie / varmuuskopioi", + buy_bitcoin: "Osta Bitcoinia", + show_xpub: "Näytä lompakon XPUB" }, export: { - title: 'lompakon vienti', + title: "lompakon vienti" }, xpub: { - title: 'lompakon XPUB', - copiedToClipboard: 'Kopioitu leikepöydälle.', + title: "lompakon XPUB", + copiedToClipboard: "Kopioitu leikepöydälle." }, import: { - title: 'tuo', + title: "tuo", explanation: - 'Kirjoita tähän muistisanasi, private key, WIF tai jotain mitä sinulla on. Veles Wallet tekee parhaansa arvatakseen oikean muodon ja tuo lompakkosi', - imported: 'Tuotu', - error: 'Tuonti epäonnistui. Varmista, että annettu tieto on oikein', - success: 'Onnistui', - do_import: 'Tuo', - scan_qr: 'tai skannaa QR-koodi?', + "Kirjoita tähän muistisanasi, private key, WIF tai jotain mitä sinulla on. Veles Wallet tekee parhaansa arvatakseen oikean muodon ja tuo lompakkosi", + imported: "Tuotu", + error: "Tuonti epäonnistui. Varmista, että annettu tieto on oikein", + success: "Onnistui", + do_import: "Tuo", + scan_qr: "tai skannaa QR-koodi?" }, scanQrWif: { - go_back: 'Mene Takaisin', - cancel: 'Peruuta', - decoding: 'Dekoodataan', - input_password: 'Anna salasana', - password_explain: 'Tämä on BIP38 salattu private key', - bad_password: 'Väärä salasana', - wallet_already_exists: 'Lompakko on jo olemassa', - bad_wif: 'Väärä WIF', - imported_wif: 'WIF tuotu ', - with_address: ' osoitteella ', - imported_segwit: 'SegWit tuotu', - imported_legacy: 'Legacy tuotu', - imported_watchonly: 'Watch-only tuotu', - }, + go_back: "Mene Takaisin", + cancel: "Peruuta", + decoding: "Dekoodataan", + input_password: "Anna salasana", + password_explain: "Tämä on BIP38 salattu private key", + bad_password: "Väärä salasana", + wallet_already_exists: "Lompakko on jo olemassa", + bad_wif: "Väärä WIF", + imported_wif: "WIF tuotu ", + with_address: " osoitteella ", + imported_segwit: "SegWit tuotu", + imported_legacy: "Legacy tuotu", + imported_watchonly: "Watch-only tuotu" + } }, transactions: { list: { - tabBarLabel: 'Siirrot', - title: 'siirrot', - description: 'Lompakkojesi saapuvat ja lähtevät siirrot', - conf: 'conf', + tabBarLabel: "Siirrot", + title: "siirrot", + description: "Lompakkojesi saapuvat ja lähtevät siirrot", + conf: "conf" }, details: { - title: 'Siirto', - from: 'Input', - to: 'Output', - copy: 'Kopioi', - transaction_details: 'Siirron tiedot', - show_in_block_explorer: 'Näytä lohkoketjuselaimessa', - }, + title: "Siirto", + from: "Input", + to: "Output", + copy: "Kopioi", + transaction_details: "Siirron tiedot", + show_in_block_explorer: "Näytä lohkoketjuselaimessa" + } }, send: { - header: 'Lähetä', + header: "Lähetä", details: { - title: 'luo siirto', - amount_field_is_not_valid: 'Määrä ei kelpaa', - fee_field_is_not_valid: 'Siirtokulu ei kelpaa', - address_field_is_not_valid: 'Osoite ei kelpaa', - total_exceeds_balance: 'Lähetettävä summa ylittää katteen', - create_tx_error: 'Virhe siirron luonnissa. Varmista, että osoite on oikein.', - address: 'osoite', - amount_placeholder: 'lähetettävä summa (VLS)', - fee_placeholder: 'plus siirtokulu (VLS)', - note_placeholder: 'muistiinpano', - cancel: 'Peruuta', - scan: 'Skannaa', - send: 'Lähetä', - create: 'Luo', - remaining_balance: 'Jäljellä oleva kate', + title: "luo siirto", + amount_field_is_not_valid: "Määrä ei kelpaa", + fee_field_is_not_valid: "Siirtokulu ei kelpaa", + address_field_is_not_valid: "Osoite ei kelpaa", + total_exceeds_balance: "Lähetettävä summa ylittää katteen", + create_tx_error: + "Virhe siirron luonnissa. Varmista, että osoite on oikein.", + address: "osoite", + amount_placeholder: "lähetettävä summa (VLS)", + fee_placeholder: "plus siirtokulu (VLS)", + note_placeholder: "muistiinpano", + cancel: "Peruuta", + scan: "Skannaa", + send: "Lähetä", + create: "Luo", + remaining_balance: "Jäljellä oleva kate" }, confirm: { - header: 'Vahvista', - sendNow: 'Lähetä nyt', + header: "Vahvista", + sendNow: "Lähetä nyt" }, success: { - done: 'Valmis', + done: "Valmis" }, create: { - details: 'Tiedot', - title: 'luo siirto', - error: 'Virhe siirron luonnissa. Väärä osoite tai lähetettävä summa?', - go_back: 'Mene Takaisin', - this_is_hex: 'Tämä on siirron hex, allekirjoitettu ja valmis kuulutettavaksi verkkoon.', - to: 'Vastaanottaja', - amount: 'Summa', - fee: 'Kulu', - tx_size: 'TX koko', - satoshi_per_byte: 'Satoshia per tavu', - memo: 'Memo', - broadcast: 'Kuuluta', - not_enough_fee: 'Kulu ei riitä. Korota kulua.', - }, + details: "Tiedot", + title: "luo siirto", + error: "Virhe siirron luonnissa. Väärä osoite tai lähetettävä summa?", + go_back: "Mene Takaisin", + this_is_hex: + "Tämä on siirron hex, allekirjoitettu ja valmis kuulutettavaksi verkkoon.", + to: "Vastaanottaja", + amount: "Summa", + fee: "Kulu", + tx_size: "TX koko", + satoshi_per_byte: "Satoshia per tavu", + memo: "Memo", + broadcast: "Kuuluta", + not_enough_fee: "Kulu ei riitä. Korota kulua." + } }, receive: { - header: 'Vastaanota', + header: "Vastaanota", details: { - title: 'Jaa tämä osoite maksajalle', - share: 'jaa', - copiedToClipboard: 'Kopioitu leikepöydälle.', - label: 'Selite', - create: 'Luo', - setAmount: 'Vastaanotettava summa', + title: "Jaa tämä osoite maksajalle", + share: "jaa", + copiedToClipboard: "Kopioitu leikepöydälle.", + label: "Selite", + create: "Luo", + setAmount: "Vastaanotettava summa" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Osta Bitcoinia', - tap_your_address: 'Napsauta osoitettasi kopioidaksesi sen leikepöydälle:', - copied: 'Kopioitu leikepöydälle!', + header: "Osta Bitcoinia", + tap_your_address: "Napsauta osoitettasi kopioidaksesi sen leikepöydälle:", + copied: "Kopioitu leikepöydälle!" }, settings: { - header: 'asetukset', - plausible_deniability: 'Uskottava kiistettävyys...', - storage_not_encrypted: 'Tallennustila: salaamaton', - storage_encrypted: 'Tallennustila: salattu', - password: 'Salasana', - password_explain: 'Luo salasana, jota käytät tallennustilan salauksen purkamiseen', - retype_password: 'Salasana uudelleen', - passwords_do_not_match: 'Salasanat eivät täsmää', - encrypt_storage: 'Salaa tallennustila', - lightning_settings: 'Lightning asetukset', + header: "asetukset", + plausible_deniability: "Uskottava kiistettävyys...", + storage_not_encrypted: "Tallennustila: salaamaton", + storage_encrypted: "Tallennustila: salattu", + password: "Salasana", + password_explain: + "Luo salasana, jota käytät tallennustilan salauksen purkamiseen", + retype_password: "Salasana uudelleen", + passwords_do_not_match: "Salasanat eivät täsmää", + encrypt_storage: "Salaa tallennustila", + lightning_settings: "Lightning asetukset", lightning_settings_explain: - 'Yhdistääksesi omaan LND noodiin, asenna LndHub' + - ' ja laita sen URL tänne. Jätä tyhjäksi käyttääksesi Veles Walletin LNDHubia (lndhub.io). Muutosten tallentamisen jälkeen luodut lompakot yhdistävät annettuun LNDHubiin.', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Tallenna', - about: 'Tietoa', - language: 'Kieli', - currency: 'Valuutta', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Yhdistääksesi omaan LND noodiin, asenna LndHub" + + " ja laita sen URL tänne. Jätä tyhjäksi käyttääksesi Veles Walletin LNDHubia (lndhub.io). Muutosten tallentamisen jälkeen luodut lompakot yhdistävät annettuun LNDHubiin.", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Tallenna", + about: "Tietoa", + language: "Kieli", + currency: "Valuutta", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Uskottava Kiistettävyys', + title: "Uskottava Kiistettävyys", help: - 'Joissain tilanteissa, saatat olla pakotettu kertomaan ' + - 'salasanasi. Pitääksesi kolikkosi turvassa, Veles Wallet voi luoda toisen ' + - 'salatun tallennustilan, toisella salasanalla. Paineen alla, ' + - 'voit kertoa tämän salasanan kolmannelle osapuolelle. Annettaessa ' + - 'Veles Walletiin, se avaa uuden väärennetyn tallennustilan. Se näyttää ' + - 'oikealta kolmannelle osapuolelle, mutta pitää oikean tallennustilasi ' + - 'kolikkoineen turvassa.', - help2: 'Uusi tallennustila näyttää täysin toimivalta, ja voit säilyttää ' + 'pieniä summia siellä, jotta se näyttää uskottavalta.', - create_fake_storage: 'Luo väärennetty tallennustila', - go_back: 'Mene Takaisin', - create_password: 'Luo salasana', - create_password_explanation: 'Väärennetyn tallennustilan salasanan ei tule täsmätä oikean tallennustilan salasanan kanssa', - password_should_not_match: 'Väärennetyn tallennustilan salasanan ei tule täsmätä oikean tallennustilan salasanan kanssa', - retype_password: 'Salasana uudelleen', - passwords_do_not_match: 'Salasanat eivät täsmää, yritä uudelleen', - success: 'Onnistui', + "Joissain tilanteissa, saatat olla pakotettu kertomaan " + + "salasanasi. Pitääksesi kolikkosi turvassa, Veles Wallet voi luoda toisen " + + "salatun tallennustilan, toisella salasanalla. Paineen alla, " + + "voit kertoa tämän salasanan kolmannelle osapuolelle. Annettaessa " + + "Veles Walletiin, se avaa uuden väärennetyn tallennustilan. Se näyttää " + + "oikealta kolmannelle osapuolelle, mutta pitää oikean tallennustilasi " + + "kolikkoineen turvassa.", + help2: + "Uusi tallennustila näyttää täysin toimivalta, ja voit säilyttää " + + "pieniä summia siellä, jotta se näyttää uskottavalta.", + create_fake_storage: "Luo väärennetty tallennustila", + go_back: "Mene Takaisin", + create_password: "Luo salasana", + create_password_explanation: + "Väärennetyn tallennustilan salasanan ei tule täsmätä oikean tallennustilan salasanan kanssa", + password_should_not_match: + "Väärennetyn tallennustilan salasanan ei tule täsmätä oikean tallennustilan salasanan kanssa", + retype_password: "Salasana uudelleen", + passwords_do_not_match: "Salasanat eivät täsmää, yritä uudelleen", + success: "Onnistui" }, lnd: { - title: 'hallinnoi varoja', - choose_source_wallet: 'Valitse lähdelompakko', - refill_lnd_balance: 'Täytä Lightning lompakon katetta', - refill: 'Täytä', - withdraw: 'Nosta', - expired: 'Erääntynyt', - placeholder: 'Lasku', - sameWalletAsInvoiceError: 'Et voi maksaa laskua samalla lompakolla, jolla se on luotu.', + title: "hallinnoi varoja", + choose_source_wallet: "Valitse lähdelompakko", + refill_lnd_balance: "Täytä Lightning lompakon katetta", + refill: "Täytä", + withdraw: "Nosta", + expired: "Erääntynyt", + placeholder: "Lasku", + sameWalletAsInvoiceError: + "Et voi maksaa laskua samalla lompakolla, jolla se on luotu." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/fr_FR.js b/loc/fr_FR.js index 978f3991c39..834dbb06ebb 100644 --- a/loc/fr_FR.js +++ b/loc/fr_FR.js @@ -1,246 +1,261 @@ module.exports = { _: { - storage_is_encrypted: "L'espace de stockage est chiffré. Mot de passe requis pour le déchiffrer.", - enter_password: 'Saisir mot de passe', - bad_password: 'Mauvais mot de passe, ré-essayer', - never: 'jamais', - continue: 'Continue', - ok: 'OK', + storage_is_encrypted: + "L'espace de stockage est chiffré. Mot de passe requis pour le déchiffrer.", + enter_password: "Saisir mot de passe", + bad_password: "Mauvais mot de passe, ré-essayer", + never: "jamais", + continue: "Continue", + ok: "OK" }, wallets: { - select_wallet: 'Choix du portefeuille', - options: 'options', - createBitcoinWallet: 'In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?', + select_wallet: "Choix du portefeuille", + options: "options", + createBitcoinWallet: + "In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?", list: { - app_name: 'Veles Wallet', - title: 'portefeuilles', + app_name: "Veles Wallet", + title: "portefeuilles", header: - 'Un portefeuille represente une paire de clées (publique/privée) et une adresse que vous pouvez partager pour recevoir des transactions.', - add: 'Ajouter un portefeuille', - create_a_wallet: 'Créer un portefeuille', + "Un portefeuille represente une paire de clées (publique/privée) et une adresse que vous pouvez partager pour recevoir des transactions.", + add: "Ajouter un portefeuille", + create_a_wallet: "Créer un portefeuille", create_a_wallet1: "C'est gratuit et vous pouvez en créer", - create_a_wallet2: 'autant que vous souhaitez', - latest_transaction: 'dernière transaction', - empty_txs1: 'Vos transactions apparaîtront ici,', - empty_txs2: 'Aucune pour le moment', + create_a_wallet2: "autant que vous souhaitez", + latest_transaction: "dernière transaction", + empty_txs1: "Vos transactions apparaîtront ici,", + empty_txs2: "Aucune pour le moment", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Cliquez ici pour acheter du Bitcoin', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Cliquez ici pour acheter du Bitcoin" }, reorder: { - title: 'Trier vos portefeuilles', + title: "Trier vos portefeuilles" }, add: { - title: 'ajouter un portefeuille', + title: "ajouter un portefeuille", description: - 'Vous pouvez soit scanner et importer un paper wallet (au format WIF - Wallet Import Format), ou créer un nouveau portefeuille. Compatible avec Segwit par defaut.', - scan: 'Scanner', - create: 'Créer', - label_new_segwit: 'Nouveau SegWit', - label_new_lightning: 'Nouveau Lightning', - wallet_name: 'nom du portefeuille', - wallet_type: 'type', - or: 'ou', - import_wallet: 'Importer un portefeuille', - imported: 'Importé', - coming_soon: 'Bientôt', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Vous pouvez soit scanner et importer un paper wallet (au format WIF - Wallet Import Format), ou créer un nouveau portefeuille. Compatible avec Segwit par defaut.", + scan: "Scanner", + create: "Créer", + label_new_segwit: "Nouveau SegWit", + label_new_lightning: "Nouveau Lightning", + wallet_name: "nom du portefeuille", + wallet_type: "type", + or: "ou", + import_wallet: "Importer un portefeuille", + imported: "Importé", + coming_soon: "Bientôt", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Portefeuille', - address: 'Adresse', - type: 'Type', - label: 'Libelé', - destination: 'destination', - description: 'description', - are_you_sure: 'Êtes vous sur?', - yes_delete: 'Oui, supprimer', - no_cancel: 'Non, annuler', - delete: 'Supprimer', - save: 'Sauvegarder', - delete_this_wallet: 'Supprimer ce portefeuille', - export_backup: 'Exporter / sauvegarder', - buy_bitcoin: 'Acheter du Bitcoin', - show_xpub: 'Afficher XPUB du portefeuille', + title: "Portefeuille", + address: "Adresse", + type: "Type", + label: "Libelé", + destination: "destination", + description: "description", + are_you_sure: "Êtes vous sur?", + yes_delete: "Oui, supprimer", + no_cancel: "Non, annuler", + delete: "Supprimer", + save: "Sauvegarder", + delete_this_wallet: "Supprimer ce portefeuille", + export_backup: "Exporter / sauvegarder", + buy_bitcoin: "Acheter du Bitcoin", + show_xpub: "Afficher XPUB du portefeuille" }, export: { - title: 'export du portefeuille', + title: "export du portefeuille" }, xpub: { - title: 'XPUB portefeuille', - copiedToClipboard: 'Copié dans le presse-papiers.', + title: "XPUB portefeuille", + copiedToClipboard: "Copié dans le presse-papiers." }, import: { - title: 'importer', + title: "importer", explanation: "Write here your mnemonic, private key, WIF, or anything you've got. Veles Wallet will do its best to guess the correct format and import your wallet", - imported: 'Importé', - error: "Échec de l'import. Merci, de vérifier que les données saisies sont valides.", - success: 'Succès', - do_import: 'Importer', - scan_qr: 'ou scaner un QR code', + imported: "Importé", + error: + "Échec de l'import. Merci, de vérifier que les données saisies sont valides.", + success: "Succès", + do_import: "Importer", + scan_qr: "ou scaner un QR code" }, scanQrWif: { - go_back: 'Retour', - cancel: 'Annuler', - decoding: 'Déchiffrage', - input_password: 'Saisir mot de passe', - password_explain: 'Ceci est une clée privée chiffrée avec BIP38', - bad_password: 'Mauvais mot de passe', - wallet_already_exists: 'Ce portefeuille existe déjà', - bad_wif: 'Mauvais WIF', - imported_wif: 'WIF Importé', - with_address: ' avec adresse ', - imported_segwit: 'SegWit Importé', - imported_legacy: 'Legacy Importé', - imported_watchonly: 'Monitoring Importé', - }, + go_back: "Retour", + cancel: "Annuler", + decoding: "Déchiffrage", + input_password: "Saisir mot de passe", + password_explain: "Ceci est une clée privée chiffrée avec BIP38", + bad_password: "Mauvais mot de passe", + wallet_already_exists: "Ce portefeuille existe déjà", + bad_wif: "Mauvais WIF", + imported_wif: "WIF Importé", + with_address: " avec adresse ", + imported_segwit: "SegWit Importé", + imported_legacy: "Legacy Importé", + imported_watchonly: "Monitoring Importé" + } }, transactions: { list: { - tabBarLabel: 'Transactions', - title: 'transactions', - description: 'Une liste des transactions entrentes et sortantes de vos portefeuilles', - conf: 'conf', + tabBarLabel: "Transactions", + title: "transactions", + description: + "Une liste des transactions entrentes et sortantes de vos portefeuilles", + conf: "conf" }, details: { - title: 'Transaction', - from: 'De', - to: 'À', - copy: 'Copier', - transaction_details: 'Détails de la transaction', - show_in_block_explorer: 'Afficher dans le "block explorer"', - }, + title: "Transaction", + from: "De", + to: "À", + copy: "Copier", + transaction_details: "Détails de la transaction", + show_in_block_explorer: 'Afficher dans le "block explorer"' + } }, send: { - header: 'Envoyer', + header: "Envoyer", details: { - title: 'créer une transaction', - amount_field_is_not_valid: 'Champ montant invalide', - fee_field_is_not_valid: 'Champ frais invalide', - address_field_is_not_valid: 'Champ adresse invalide', - total_exceeds_balance: 'Le montant à envoyer excède le montant disponible.', - create_tx_error: 'There was an error creating the transaction. Please, make sure the address is valid.', - address: 'adresse', - amount_placeholder: 'montant à envoyer (en VLS)', - fee_placeholder: 'plus frais de transaction (en VLS)', - note_placeholder: 'note (optionnelle)', - cancel: 'Annuler', - scan: 'Scanner', - send: 'Envoyer', - create: 'Créer', - remaining_balance: 'Balance restante', + title: "créer une transaction", + amount_field_is_not_valid: "Champ montant invalide", + fee_field_is_not_valid: "Champ frais invalide", + address_field_is_not_valid: "Champ adresse invalide", + total_exceeds_balance: + "Le montant à envoyer excède le montant disponible.", + create_tx_error: + "There was an error creating the transaction. Please, make sure the address is valid.", + address: "adresse", + amount_placeholder: "montant à envoyer (en VLS)", + fee_placeholder: "plus frais de transaction (en VLS)", + note_placeholder: "note (optionnelle)", + cancel: "Annuler", + scan: "Scanner", + send: "Envoyer", + create: "Créer", + remaining_balance: "Balance restante" }, confirm: { - header: 'Confirmer', - sendNow: 'Envoyer maintenant', + header: "Confirmer", + sendNow: "Envoyer maintenant" }, success: { - done: 'Terminé', + done: "Terminé" }, create: { - details: 'Details', - title: 'créer une transaction', - error: 'Erreur creating transaction. Invalid address or send amount?', - go_back: 'Retour', - this_is_hex: 'This is transaction hex, signed and ready to be broadcast to the network.', - to: 'À', - amount: 'Montant', - fee: 'Frais', - tx_size: 'Taille de la Transaction (TX size)', - satoshi_per_byte: 'Satoshi par byte', - memo: 'Memo', - broadcast: 'Broadcast', - not_enough_fee: 'Frais insufisants. Veuillez augmenter les frais', - }, + details: "Details", + title: "créer une transaction", + error: "Erreur creating transaction. Invalid address or send amount?", + go_back: "Retour", + this_is_hex: + "This is transaction hex, signed and ready to be broadcast to the network.", + to: "À", + amount: "Montant", + fee: "Frais", + tx_size: "Taille de la Transaction (TX size)", + satoshi_per_byte: "Satoshi par byte", + memo: "Memo", + broadcast: "Broadcast", + not_enough_fee: "Frais insufisants. Veuillez augmenter les frais" + } }, receive: { - header: 'Recevoir', + header: "Recevoir", details: { - title: 'Partager cette adresse avec le destinataire', - share: 'partager', - copiedToClipboard: 'Copier dans le presse-papiers.', - label: 'Description', - create: 'Create', - setAmount: 'Revevoir avec montant', + title: "Partager cette adresse avec le destinataire", + share: "partager", + copiedToClipboard: "Copier dans le presse-papiers.", + label: "Description", + create: "Create", + setAmount: "Revevoir avec montant" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Acheter du Bitcoin', - tap_your_address: 'Cliquez votre adresse pour la copier:', - copied: 'Copié dans le presse-papiers!', + header: "Acheter du Bitcoin", + tap_your_address: "Cliquez votre adresse pour la copier:", + copied: "Copié dans le presse-papiers!" }, settings: { - header: 'réglages', - plausible_deniability: 'Déni plausible...', - storage_not_encrypted: 'Stockage: non chiffré', - storage_encrypted: 'Stockage: chiffré', - password: 'Mot de passe', - password_explain: "Créer le mot de passe utilisé pour déchiffrer l'espace de stockage principal", - retype_password: 'Re-saisir votre mot de passe', - passwords_do_not_match: 'Les mots de passe ne correspondent pas', - encrypt_storage: 'Chiffrer le stockage', - lightning_settings: 'Lightning settings', + header: "réglages", + plausible_deniability: "Déni plausible...", + storage_not_encrypted: "Stockage: non chiffré", + storage_encrypted: "Stockage: chiffré", + password: "Mot de passe", + password_explain: + "Créer le mot de passe utilisé pour déchiffrer l'espace de stockage principal", + retype_password: "Re-saisir votre mot de passe", + passwords_do_not_match: "Les mots de passe ne correspondent pas", + encrypt_storage: "Chiffrer le stockage", + lightning_settings: "Lightning settings", lightning_settings_explain: - 'To connect to your own LND node please install LndHub' + - ' and put its URL here in settings. Leave blank to use default ' + - 'ndHub\n (lndhub.io)', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'save', - about: 'À propos', - language: 'Langue', - currency: 'Devise', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "To connect to your own LND node please install LndHub" + + " and put its URL here in settings. Leave blank to use default " + + "ndHub\n (lndhub.io)", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "save", + about: "À propos", + language: "Langue", + currency: "Devise", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Déni plausible', + title: "Déni plausible", help: - 'Dans certaines circonstances, vous serez peut-être forcé par un tiers à communiquer ' + - 'votre mot de passe. Pour protéger vos biens, Veles Wallet permet de créer un autre ' + - 'espace de stockage, avec un mot de passe différent. Sous la contrainte, ' + - 'vous pourrez divulger ce mot de passe au tier. Quand il est saisi ' + + "Dans certaines circonstances, vous serez peut-être forcé par un tiers à communiquer " + + "votre mot de passe. Pour protéger vos biens, Veles Wallet permet de créer un autre " + + "espace de stockage, avec un mot de passe différent. Sous la contrainte, " + + "vous pourrez divulger ce mot de passe au tier. Quand il est saisi " + "Veles Wallet, débloquera se 'faux' espace de stockage. Le tiers pourra " + - 'confondre ces données avec des données légitimes, votre espace de stockage ' + + "confondre ces données avec des données légitimes, votre espace de stockage " + "principal restera sécurisé et hors d'atteinte.", - help2: 'New storage will be fully functional, and you can store some ' + 'minimum amounts there so it looks more believable.', - create_fake_storage: 'Créer un faux espace de stockage chiffré', - go_back: 'Retour', - create_password: 'Créer un mot de passe', - create_password_explanation: 'Le mot de passe pour le faux espace de stockage ne doit pas être le même que celui du stockage principal', - password_should_not_match: 'Le mot de passe pour le faux espace de stockage ne doit pas être le même que celui du stockage principal', - retype_password: 'Confirmation du mot de passe', - passwords_do_not_match: 'Vos mot de passe ne sont pas identiques, veillez ré-essayer', - success: 'Succès', + help2: + "New storage will be fully functional, and you can store some " + + "minimum amounts there so it looks more believable.", + create_fake_storage: "Créer un faux espace de stockage chiffré", + go_back: "Retour", + create_password: "Créer un mot de passe", + create_password_explanation: + "Le mot de passe pour le faux espace de stockage ne doit pas être le même que celui du stockage principal", + password_should_not_match: + "Le mot de passe pour le faux espace de stockage ne doit pas être le même que celui du stockage principal", + retype_password: "Confirmation du mot de passe", + passwords_do_not_match: + "Vos mot de passe ne sont pas identiques, veillez ré-essayer", + success: "Succès" }, lnd: { - title: 'gérer vos fonds', - choose_source_wallet: 'Choisir un portefeuille source', - refill_lnd_balance: 'Déposer des fonds dans votre portfeuille Lightning', - refill: 'Déposer des fonds', - withdraw: 'Retirer des fonds', - placeholder: 'Invoice', - expired: 'Expiré', - sameWalletAsInvoiceError: 'Vous ne pouvez pas payer une facture avec le même portefeuille utilisé pour la créer.', + title: "gérer vos fonds", + choose_source_wallet: "Choisir un portefeuille source", + refill_lnd_balance: "Déposer des fonds dans votre portfeuille Lightning", + refill: "Déposer des fonds", + withdraw: "Retirer des fonds", + placeholder: "Invoice", + expired: "Expiré", + sameWalletAsInvoiceError: + "Vous ne pouvez pas payer une facture avec le même portefeuille utilisé pour la créer." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/hr_HR.js b/loc/hr_HR.js index 0a7a896293d..95bb669bae3 100644 --- a/loc/hr_HR.js +++ b/loc/hr_HR.js @@ -1,241 +1,254 @@ module.exports = { _: { - storage_is_encrypted: 'Vaš spremnik je kriptiran. Za dekripcoju je potrebna lozinka.', - enter_password: 'Unesi lozinku', - bad_password: 'Kriva lozinka, pokušaj ponovo', - never: 'nikad', - continue: 'Nastavi', - ok: 'U redu', + storage_is_encrypted: + "Vaš spremnik je kriptiran. Za dekripcoju je potrebna lozinka.", + enter_password: "Unesi lozinku", + bad_password: "Kriva lozinka, pokušaj ponovo", + never: "nikad", + continue: "Nastavi", + ok: "U redu" }, wallets: { - select_wallet: 'Odaberi volet', - options: 'opcije', + select_wallet: "Odaberi volet", + options: "opcije", list: { - app_name: 'Veles Wallet', - title: 'Voleti', - header: 'Volet je par privatnog ključa (tajna!) i javne adrese ' + 'koju slobodno možete dijeliti kada primate novce.', - add: 'Dodaj volet', - create_a_wallet: 'Stvori novi volet', - create_a_wallet1: 'Ne košta ništa i možete', - create_a_wallet2: 'ih stvoriti moliko želite', - latest_transaction: 'posljednja transakcija', - empty_txs1: 'Vaše transakcije će se pojaviti ovdje', - empty_txs2: 'trenutno nema nijedne', + app_name: "Veles Wallet", + title: "Voleti", + header: + "Volet je par privatnog ključa (tajna!) i javne adrese " + + "koju slobodno možete dijeliti kada primate novce.", + add: "Dodaj volet", + create_a_wallet: "Stvori novi volet", + create_a_wallet1: "Ne košta ništa i možete", + create_a_wallet2: "ih stvoriti moliko želite", + latest_transaction: "posljednja transakcija", + empty_txs1: "Vaše transakcije će se pojaviti ovdje", + empty_txs2: "trenutno nema nijedne", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Klikni ovdje za kupnju Bitkoina', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Klikni ovdje za kupnju Bitkoina" }, reorder: { - title: 'Uredi volete', + title: "Uredi volete" }, add: { - title: 'Dodaj volet', - description: 'Možete ili skenirati bekap papirnati volet (u WIF - Wallet Import Format), ili stvoriti novi volet. Segwit je podržan.', - scan: 'Skeniraj', - create: 'Stvori', - label_new_segwit: 'Novi SegWit', - label_new_lightning: 'Novi Lightning', - wallet_name: 'ime voleta:', - wallet_type: 'tip:', - or: 'ili', - import_wallet: 'Unesi vanjski volet', - imported: 'Unešeno', - coming_soon: 'Dolazi uskoro', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + title: "Dodaj volet", + description: + "Možete ili skenirati bekap papirnati volet (u WIF - Wallet Import Format), ili stvoriti novi volet. Segwit je podržan.", + scan: "Skeniraj", + create: "Stvori", + label_new_segwit: "Novi SegWit", + label_new_lightning: "Novi Lightning", + wallet_name: "ime voleta:", + wallet_type: "tip:", + or: "ili", + import_wallet: "Unesi vanjski volet", + imported: "Unešeno", + coming_soon: "Dolazi uskoro", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Volet', - address: 'Adresa', - type: 'Tip', - label: 'Oznaka', - destination: 'odredište', - description: 'opis', - are_you_sure: 'Jesi li ziher?', - yes_delete: 'Da, briši', - no_cancel: 'Ne, otiaži', - delete: 'Obriši', - save: 'Spremi', - delete_this_wallet: 'Obriši ovaj volet', - export_backup: 'Izvoz / bekap', - buy_bitcoin: 'Kupovina Bitcoina', - show_xpub: 'Prikaži voletov XPUB', + title: "Volet", + address: "Adresa", + type: "Tip", + label: "Oznaka", + destination: "odredište", + description: "opis", + are_you_sure: "Jesi li ziher?", + yes_delete: "Da, briši", + no_cancel: "Ne, otiaži", + delete: "Obriši", + save: "Spremi", + delete_this_wallet: "Obriši ovaj volet", + export_backup: "Izvoz / bekap", + buy_bitcoin: "Kupovina Bitcoina", + show_xpub: "Prikaži voletov XPUB" }, export: { - title: 'izvoz voleta', + title: "izvoz voleta" }, xpub: { - title: 'volet XPUB', - copiedToClipboard: 'Kopirano u međuspremnik.', + title: "volet XPUB", + copiedToClipboard: "Kopirano u međuspremnik." }, import: { - title: 'unesi', + title: "unesi", explanation: - 'Ovdje upiši svoj mnemonik slijed riječi, privatni ključ, WIF, ili što već imaš. Veles Wallet će pokušati porocijeniti format i unesti tvoj volet.', - imported: 'Uneseno', - error: 'Neuspješan unos. Molimo pažljivo provjerite ispravnost unesenih podataka.', - success: 'Uspjeh', - do_import: 'Unesi', - scan_qr: 'ili skeniraj QR kod?', + "Ovdje upiši svoj mnemonik slijed riječi, privatni ključ, WIF, ili što već imaš. Veles Wallet će pokušati porocijeniti format i unesti tvoj volet.", + imported: "Uneseno", + error: + "Neuspješan unos. Molimo pažljivo provjerite ispravnost unesenih podataka.", + success: "Uspjeh", + do_import: "Unesi", + scan_qr: "ili skeniraj QR kod?" }, scanQrWif: { - go_back: 'Povratak', - cancel: 'Otkaži', - decoding: 'Dekodiranje', - input_password: 'Unesi lozinku', - password_explain: 'Ovo je BIP38 enkriptiran privatni ključ', - bad_password: 'Pogrešna lozinka', - wallet_already_exists: 'Ovaj volet već postoji', - bad_wif: 'Pogrešan WIF', - imported_wif: 'Unesen WIF ', - with_address: ' sa adresom ', - imported_segwit: 'Unesen SegWit', - imported_legacy: 'Unesen Legacy', - imported_watchonly: 'Unesen samo za pregled', - }, + go_back: "Povratak", + cancel: "Otkaži", + decoding: "Dekodiranje", + input_password: "Unesi lozinku", + password_explain: "Ovo je BIP38 enkriptiran privatni ključ", + bad_password: "Pogrešna lozinka", + wallet_already_exists: "Ovaj volet već postoji", + bad_wif: "Pogrešan WIF", + imported_wif: "Unesen WIF ", + with_address: " sa adresom ", + imported_segwit: "Unesen SegWit", + imported_legacy: "Unesen Legacy", + imported_watchonly: "Unesen samo za pregled" + } }, transactions: { list: { - tabBarLabel: 'Transakcije', - title: 'transakcije', - description: 'Popis dolaznih i odlaznih transakcija vašeg voleta.', - conf: 'konf.', + tabBarLabel: "Transakcije", + title: "transakcije", + description: "Popis dolaznih i odlaznih transakcija vašeg voleta.", + conf: "konf." }, details: { - title: 'Transakcija', - from: 'Od', - to: 'Za', - copy: 'Kopiraj', - transaction_details: 'Detalji transakcije', - show_in_block_explorer: 'Prikaži u blok eksploreru', - }, + title: "Transakcija", + from: "Od", + to: "Za", + copy: "Kopiraj", + transaction_details: "Detalji transakcije", + show_in_block_explorer: "Prikaži u blok eksploreru" + } }, send: { - header: 'Šalji', + header: "Šalji", details: { - title: 'Stvori transakciju', - amount_field_is_not_valid: 'Iznos nije ispravan', - fee_field_is_not_valid: 'Ovo polje nije ispravno', - address_field_is_not_valid: 'Polje adrese nije ispravno', - total_exceeds_balance: 'Iznos je veći od raspoloživog.', - create_tx_error: 'Pogreška prilikom stvaranja transakcije. Molimo provijeri da je adresa ispravna.', - address: 'adresa', - amount_placeholder: 'iznos za slanje (u VLS)', - fee_placeholder: 'plus trošak transakcije (u VLS)', - note_placeholder: 'bilješka za evidenciju', - cancel: 'Otkaži', - scan: 'Skeniraj', - send: 'Šalji', - create: 'Stvori', - remaining_balance: 'Preostali saldo', + title: "Stvori transakciju", + amount_field_is_not_valid: "Iznos nije ispravan", + fee_field_is_not_valid: "Ovo polje nije ispravno", + address_field_is_not_valid: "Polje adrese nije ispravno", + total_exceeds_balance: "Iznos je veći od raspoloživog.", + create_tx_error: + "Pogreška prilikom stvaranja transakcije. Molimo provijeri da je adresa ispravna.", + address: "adresa", + amount_placeholder: "iznos za slanje (u VLS)", + fee_placeholder: "plus trošak transakcije (u VLS)", + note_placeholder: "bilješka za evidenciju", + cancel: "Otkaži", + scan: "Skeniraj", + send: "Šalji", + create: "Stvori", + remaining_balance: "Preostali saldo" }, confirm: { - header: 'Potvrdi', - sendNow: 'Pošalji sad', + header: "Potvrdi", + sendNow: "Pošalji sad" }, success: { - done: 'U redu', + done: "U redu" }, create: { - details: 'Detalji', - title: 'stvori transakciju', - error: 'Pogreška. Neispravna adresa ili iznos slanja?', - go_back: 'Nazad', - this_is_hex: 'Ovoj je hex transakcije, potpisan i spreman za objavljivanje na mrežu.', - to: 'Za', - amount: 'Iznos', - fee: 'Trošak slanja', - tx_size: 'TX veličina', - satoshi_per_byte: 'Satoshi / byte', - memo: 'Bilješka', - broadcast: 'Objavi', - not_enough_fee: 'Trošak slanja je premalen. Povećaj ga.', - }, + details: "Detalji", + title: "stvori transakciju", + error: "Pogreška. Neispravna adresa ili iznos slanja?", + go_back: "Nazad", + this_is_hex: + "Ovoj je hex transakcije, potpisan i spreman za objavljivanje na mrežu.", + to: "Za", + amount: "Iznos", + fee: "Trošak slanja", + tx_size: "TX veličina", + satoshi_per_byte: "Satoshi / byte", + memo: "Bilješka", + broadcast: "Objavi", + not_enough_fee: "Trošak slanja je premalen. Povećaj ga." + } }, receive: { - header: 'Primi', + header: "Primi", details: { - title: 'Pokaži ovu adresu platitelju', - share: 'podijeli', - copiedToClipboard: 'Kopirano u međuspremnik.', - label: 'Opis', - create: 'Stvori', - setAmount: 'Odredi iznos za primiti', + title: "Pokaži ovu adresu platitelju", + share: "podijeli", + copiedToClipboard: "Kopirano u međuspremnik.", + label: "Opis", + create: "Stvori", + setAmount: "Odredi iznos za primiti" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Kupovina Bitcoina', - tap_your_address: 'Klikni na adresu za spremanje u međuspremnik:', - copied: 'Spremljeno u međuspremnik!', + header: "Kupovina Bitcoina", + tap_your_address: "Klikni na adresu za spremanje u međuspremnik:", + copied: "Spremljeno u međuspremnik!" }, settings: { - header: 'Postavke', - plausible_deniability: 'Fejk volet...', - storage_not_encrypted: 'Spremnik: nije kriptiran', - storage_encrypted: 'Spremnik: je kriptiran', - password: 'Lozinka', - password_explain: 'Upiši lozinku koja će dekriptirati spremnik.', - retype_password: 'Ponovi lozinku', - passwords_do_not_match: 'Lozinke su različite', - encrypt_storage: 'Kriptiraj spremnik', - lightning_settings: 'Lightning postavke', + header: "Postavke", + plausible_deniability: "Fejk volet...", + storage_not_encrypted: "Spremnik: nije kriptiran", + storage_encrypted: "Spremnik: je kriptiran", + password: "Lozinka", + password_explain: "Upiši lozinku koja će dekriptirati spremnik.", + retype_password: "Ponovi lozinku", + passwords_do_not_match: "Lozinke su različite", + encrypt_storage: "Kriptiraj spremnik", + lightning_settings: "Lightning postavke", lightning_settings_explain: - 'Za spajanje na tvoj vlastiti LND čvor trebaš instalirati LndHub' + - ' i upisati njegov URL ovdje. Ostavi prazno za standardni ' + - 'ndHub\n (lndhub.io)', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Spremi', - about: 'Informacije', - language: 'Jezik', - currency: 'Valuta', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Za spajanje na tvoj vlastiti LND čvor trebaš instalirati LndHub" + + " i upisati njegov URL ovdje. Ostavi prazno za standardni " + + "ndHub\n (lndhub.io)", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Spremi", + about: "Informacije", + language: "Jezik", + currency: "Valuta", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Fejk volet', + title: "Fejk volet", help: - 'Pazi. Netko gadan te može u iznimnim okolnostima (pljačka, prijevremeni izbori, itd.) ' + - 'brutalno pritisnuti da mu otkriješ lozinku za svoj volet. ' + - 'Veles Wallet ti čuva leđa buraz. Nemaš brige. Gledaj, ' + - 'stvoriti ćemo fejk volet sa drugačijom lozinkom. Haha, žišku? ' + - 'Pa kad se ovaj počne pjeniti, a ti vidiš da je vrag odnio šalu, ' + - 'samo mu podvali lozinku za ovaj drugi volet. Eto mu ga. Nek si cucla. ', - help2: 'Novi spremnik će biti posve funkcionalan, možeš pohraniti koliko ' + 'misliš da je potrebno da izgleda uvjerljivo.', - create_fake_storage: 'Stvori fejk enkriptirani spremnik', - go_back: 'Povratak', - create_password: 'Unesi lozinku', - create_password_explanation: 'Lozinka za fejk spremnik treba biti drugačija od lozinke za oriđi spremnik', - password_should_not_match: 'Lozinka za fejk spremnik treba biti drugačija od lozinke za oriđi spremnik', - retype_password: 'Ponovi lozinku', - passwords_do_not_match: 'Lozinke ne pašu, pokušaj ponovo', - success: 'Uspjeh', + "Pazi. Netko gadan te može u iznimnim okolnostima (pljačka, prijevremeni izbori, itd.) " + + "brutalno pritisnuti da mu otkriješ lozinku za svoj volet. " + + "Veles Wallet ti čuva leđa buraz. Nemaš brige. Gledaj, " + + "stvoriti ćemo fejk volet sa drugačijom lozinkom. Haha, žišku? " + + "Pa kad se ovaj počne pjeniti, a ti vidiš da je vrag odnio šalu, " + + "samo mu podvali lozinku za ovaj drugi volet. Eto mu ga. Nek si cucla. ", + help2: + "Novi spremnik će biti posve funkcionalan, možeš pohraniti koliko " + + "misliš da je potrebno da izgleda uvjerljivo.", + create_fake_storage: "Stvori fejk enkriptirani spremnik", + go_back: "Povratak", + create_password: "Unesi lozinku", + create_password_explanation: + "Lozinka za fejk spremnik treba biti drugačija od lozinke za oriđi spremnik", + password_should_not_match: + "Lozinka za fejk spremnik treba biti drugačija od lozinke za oriđi spremnik", + retype_password: "Ponovi lozinku", + passwords_do_not_match: "Lozinke ne pašu, pokušaj ponovo", + success: "Uspjeh" }, lnd: { - title: 'Uredi novčeke', - choose_source_wallet: 'Odaberi izvor', - refill_lnd_balance: 'Dopuni Lightning volet saldo', - refill: 'Dopuni', - withdraw: 'Isprazni', - placeholder: 'Invoice', - expired: 'Isteklo', - sameWalletAsInvoiceError: 'Buraz! Ne možeš platiti račun s istim voletom s kojim si račun stvorio, ono.', + title: "Uredi novčeke", + choose_source_wallet: "Odaberi izvor", + refill_lnd_balance: "Dopuni Lightning volet saldo", + refill: "Dopuni", + withdraw: "Isprazni", + placeholder: "Invoice", + expired: "Isteklo", + sameWalletAsInvoiceError: + "Buraz! Ne možeš platiti račun s istim voletom s kojim si račun stvorio, ono." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/hu_HU.js b/loc/hu_HU.js index 4f8a8846afa..85e958a08f1 100644 --- a/loc/hu_HU.js +++ b/loc/hu_HU.js @@ -1,243 +1,254 @@ module.exports = { _: { - storage_is_encrypted: 'A Tárhely titkosítva. Jelszó szükséges a dekódoláshoz', - enter_password: 'Írd be a jelszót', - bad_password: 'Hibás jelszó, próbáld újra', - never: 'soha', - continue: 'Folytat', - ok: 'OK', + storage_is_encrypted: + "A Tárhely titkosítva. Jelszó szükséges a dekódoláshoz", + enter_password: "Írd be a jelszót", + bad_password: "Hibás jelszó, próbáld újra", + never: "soha", + continue: "Folytat", + ok: "OK" }, wallets: { - select_wallet: 'Válassz tárcát', - options: 'beállítások', + select_wallet: "Válassz tárcát", + options: "beállítások", createBitcoinWallet: - 'Jelenleg még nincsen Bitcoin tárcád. Lightning tárca létrehozásához először készíts egy Bitcoin tárcát, vagy importálj egy már meglévő tárcát. Mindenképp folytatod?', + "Jelenleg még nincsen Bitcoin tárcád. Lightning tárca létrehozásához először készíts egy Bitcoin tárcát, vagy importálj egy már meglévő tárcát. Mindenképp folytatod?", list: { - app_name: 'Veles Wallet', - title: 'tárcák', - header: 'Egy tárca nem más, mint egy kulcspár, és egy cím. A cím nyilvános, és megoszhatod másokkal, ha szeretnél Bitcoint fogadni', - add: 'Új Tárca', - create_a_wallet: 'Új tárca', - create_a_wallet1: 'Ingyenes, és annyit hozhatsz létre', - create_a_wallet2: 'amennyit szeretnél', - latest_transaction: 'utolsó tranzakció', - empty_txs1: 'A tranzakcióid itt fognak megjelenni', - empty_txs2: 'de még nem volt tranzakciód!', + app_name: "Veles Wallet", + title: "tárcák", + header: + "Egy tárca nem más, mint egy kulcspár, és egy cím. A cím nyilvános, és megoszhatod másokkal, ha szeretnél Bitcoint fogadni", + add: "Új Tárca", + create_a_wallet: "Új tárca", + create_a_wallet1: "Ingyenes, és annyit hozhatsz létre", + create_a_wallet2: "amennyit szeretnél", + latest_transaction: "utolsó tranzakció", + empty_txs1: "A tranzakcióid itt fognak megjelenni", + empty_txs2: "de még nem volt tranzakciód!", empty_txs1_lightning: - 'A Lightning tárcát a mindennapi tranzakcióidhoz használhatod. A tranzakciók azonnal végrehajtódnak, minimális átutalási díjjal.', - empty_txs2_lightning: '\nA kezdéshez kattints a "Kezelés"-re, és töltsd fel az egyenleged.', - tap_here_to_buy: 'Bitcoin vásárláshoz kattints ide', + "A Lightning tárcát a mindennapi tranzakcióidhoz használhatod. A tranzakciók azonnal végrehajtódnak, minimális átutalási díjjal.", + empty_txs2_lightning: + '\nA kezdéshez kattints a "Kezelés"-re, és töltsd fel az egyenleged.', + tap_here_to_buy: "Bitcoin vásárláshoz kattints ide" }, reorder: { - title: 'Tárcák rendezése', + title: "Tárcák rendezése" }, add: { - title: 'új tárca', + title: "új tárca", description: - 'Beszkennelhetsz egy már meglévő tárcát (WIF formátumban - Wallet Import Format) vagy készíthetsz egy új tárcát. A Segwit tárcák alapból támogatottak.', - scan: 'Scan', - create: 'Létrehoz', - label_new_segwit: 'Új SegWit', - label_new_lightning: 'Új Lightning', - wallet_name: 'név', - wallet_type: 'típus', - or: 'vagy', - import_wallet: 'Tárca importálása', - imported: 'Importálva', - coming_soon: 'Hamarosan', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Beszkennelhetsz egy már meglévő tárcát (WIF formátumban - Wallet Import Format) vagy készíthetsz egy új tárcát. A Segwit tárcák alapból támogatottak.", + scan: "Scan", + create: "Létrehoz", + label_new_segwit: "Új SegWit", + label_new_lightning: "Új Lightning", + wallet_name: "név", + wallet_type: "típus", + or: "vagy", + import_wallet: "Tárca importálása", + imported: "Importálva", + coming_soon: "Hamarosan", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Tárca', - address: 'Cím', - type: 'Típus', - label: 'Cimke', - description: 'leírás', - are_you_sure: 'Biztos vagy benne?', - yes_delete: 'Igen, töröld', - no_cancel: 'Nem, megszakít', - delete: 'Törlés', - save: 'Ment', - delete_this_wallet: 'Töröld ezt a tárcát', - export_backup: 'Exportálás / Biztonsági mentés', - buy_bitcoin: 'Bitcoin vásáslás', - show_xpub: 'Mutasd a tárca XPUB kulcsát', + title: "Tárca", + address: "Cím", + type: "Típus", + label: "Cimke", + description: "leírás", + are_you_sure: "Biztos vagy benne?", + yes_delete: "Igen, töröld", + no_cancel: "Nem, megszakít", + delete: "Törlés", + save: "Ment", + delete_this_wallet: "Töröld ezt a tárcát", + export_backup: "Exportálás / Biztonsági mentés", + buy_bitcoin: "Bitcoin vásáslás", + show_xpub: "Mutasd a tárca XPUB kulcsát" }, export: { - title: 'tárca exportálása', + title: "tárca exportálása" }, xpub: { - title: 'a tárca XPUB kulcsa', - copiedToClipboard: 'Vágólapra másolva', + title: "a tárca XPUB kulcsa", + copiedToClipboard: "Vágólapra másolva" }, import: { - title: 'importálás', + title: "importálás", explanation: - 'Írd be a kulcsszavaidat, a titkos kulcsodat, WIF-et, vagy bármi mást. A Veles Wallet megpróbálja kitalálni a helyes formátumot, és importálja a tárcádat', - imported: 'Importálva', - error: 'Importálás sikertelen. Ellenőrizd, hogy helyes adatokat adtál-e meg.', - success: 'Sikeres importálás!', - do_import: 'Importálás', - scan_qr: 'vagy QR-kód szkennelése?', + "Írd be a kulcsszavaidat, a titkos kulcsodat, WIF-et, vagy bármi mást. A Veles Wallet megpróbálja kitalálni a helyes formátumot, és importálja a tárcádat", + imported: "Importálva", + error: + "Importálás sikertelen. Ellenőrizd, hogy helyes adatokat adtál-e meg.", + success: "Sikeres importálás!", + do_import: "Importálás", + scan_qr: "vagy QR-kód szkennelése?" }, scanQrWif: { - go_back: 'Vissza', - cancel: 'Megszakít', - decoding: 'Dekódolás', - input_password: 'Add meg a jelszavad', - password_explain: 'Ez egy BIP38-titkosított titkos kulcs', - bad_password: 'Hibás jelszó', - wallet_already_exists: 'Egy ilyen tárca már létezik', - bad_wif: 'Hibás WIF', - imported_wif: 'Importált WIF ', - with_address: ' címmel ', - imported_segwit: 'Importált SegWit', - imported_legacy: 'Importált Legacy', - imported_watchonly: 'Importált Watch-only', - }, + go_back: "Vissza", + cancel: "Megszakít", + decoding: "Dekódolás", + input_password: "Add meg a jelszavad", + password_explain: "Ez egy BIP38-titkosított titkos kulcs", + bad_password: "Hibás jelszó", + wallet_already_exists: "Egy ilyen tárca már létezik", + bad_wif: "Hibás WIF", + imported_wif: "Importált WIF ", + with_address: " címmel ", + imported_segwit: "Importált SegWit", + imported_legacy: "Importált Legacy", + imported_watchonly: "Importált Watch-only" + } }, transactions: { list: { - tabBarLabel: 'Tranzakciók', - title: 'tranzakciók', - description: 'Lista a tárcáid bejövő és kimenő tranzakcióiról', - conf: 'jóvá', + tabBarLabel: "Tranzakciók", + title: "tranzakciók", + description: "Lista a tárcáid bejövő és kimenő tranzakcióiról", + conf: "jóvá" }, details: { - title: 'Tranzakció', - from: 'Input', - to: 'Output', - copy: 'Másolás', - transaction_details: 'Tranzakció részletei', - show_in_block_explorer: 'Mutasd a block explorerben', - }, + title: "Tranzakció", + from: "Input", + to: "Output", + copy: "Másolás", + transaction_details: "Tranzakció részletei", + show_in_block_explorer: "Mutasd a block explorerben" + } }, send: { - header: 'Küldés', + header: "Küldés", details: { - title: 'tranzakció létrehozása', - amount_field_is_not_valid: 'Érvénytelen összeg', - fee_field_is_not_valid: 'Èrvénytelen tranzakciós díj', - address_field_is_not_valid: 'Érvénytelen cím', - total_exceeds_balance: 'A megadott összeg nagyobb, mint a tárca elérhető egyenlege', - create_tx_error: 'Hiba történt a tranzakció létrehozásakor. Ellenőrizd a megadott cím érvényességét.', - address: 'cím', - amount_placeholder: 'küldendő összeg (VLS)', - fee_placeholder: 'tranzakciós díj (VLS)', - note_placeholder: 'saját megjegyzés', - cancel: 'Megszakít', - scan: 'Scan', - send: 'Küldés', - create: 'Létrehoz', - remaining_balance: 'Fennmaradó egyenleg', + title: "tranzakció létrehozása", + amount_field_is_not_valid: "Érvénytelen összeg", + fee_field_is_not_valid: "Èrvénytelen tranzakciós díj", + address_field_is_not_valid: "Érvénytelen cím", + total_exceeds_balance: + "A megadott összeg nagyobb, mint a tárca elérhető egyenlege", + create_tx_error: + "Hiba történt a tranzakció létrehozásakor. Ellenőrizd a megadott cím érvényességét.", + address: "cím", + amount_placeholder: "küldendő összeg (VLS)", + fee_placeholder: "tranzakciós díj (VLS)", + note_placeholder: "saját megjegyzés", + cancel: "Megszakít", + scan: "Scan", + send: "Küldés", + create: "Létrehoz", + remaining_balance: "Fennmaradó egyenleg" }, confirm: { - header: 'Megerősítés', - sendNow: 'Küldés most', + header: "Megerősítés", + sendNow: "Küldés most" }, success: { - done: 'Kész!', + done: "Kész!" }, create: { - details: 'Részletek', - title: 'tranzakció létrehozása', - error: 'Hiba történt a tranzakció létrehozásakor. Hibás cím vagy összeg?', - go_back: 'Vissza', - this_is_hex: 'Tranzakció hexadecimális formátumban, aláírva és küldésre készen.', - to: 'Címzett', - amount: 'Összeg', - fee: 'Díj', - tx_size: 'Tranzakció mérete', - satoshi_per_byte: 'Satoshi per byte', - memo: 'Memo', - broadcast: 'Küldés', - not_enough_fee: 'Díj túl alacsony. Növeld a megadott díjat', - }, + details: "Részletek", + title: "tranzakció létrehozása", + error: "Hiba történt a tranzakció létrehozásakor. Hibás cím vagy összeg?", + go_back: "Vissza", + this_is_hex: + "Tranzakció hexadecimális formátumban, aláírva és küldésre készen.", + to: "Címzett", + amount: "Összeg", + fee: "Díj", + tx_size: "Tranzakció mérete", + satoshi_per_byte: "Satoshi per byte", + memo: "Memo", + broadcast: "Küldés", + not_enough_fee: "Díj túl alacsony. Növeld a megadott díjat" + } }, receive: { - header: 'Fogadás', + header: "Fogadás", details: { - title: 'Cím megosztása a fizető féllel', - share: 'megosztás', - copiedToClipboard: 'Vágólapra másolva.', - label: 'Leírás', - create: 'Létrehoz', - setAmount: 'Fogadandó összeg', + title: "Cím megosztása a fizető féllel", + share: "megosztás", + copiedToClipboard: "Vágólapra másolva.", + label: "Leírás", + create: "Létrehoz", + setAmount: "Fogadandó összeg" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Bitcoin vásárlása', - tap_your_address: 'Kattints a címre a vágólapra másoláshoz:', - copied: 'Vágólapra másolva!', + header: "Bitcoin vásárlása", + tap_your_address: "Kattints a címre a vágólapra másoláshoz:", + copied: "Vágólapra másolva!" }, settings: { - header: 'beállítások', - plausible_deniability: 'Elfogadható tagadhatóság...', - storage_not_encrypted: 'Tárhely: nincs titkosítva', - storage_encrypted: 'Tárhely: titkosítva', - password: 'Jelszó', - password_explain: 'Add meg a jelszót, amivel majd dekódolhatod a tárhelyet', - retype_password: 'Jelszó megerősítése', - passwords_do_not_match: 'A megadott jelszavak különböznek!', - encrypt_storage: 'Tárhely titkosítása', - lightning_settings: 'Lightning Beállítások', + header: "beállítások", + plausible_deniability: "Elfogadható tagadhatóság...", + storage_not_encrypted: "Tárhely: nincs titkosítva", + storage_encrypted: "Tárhely: titkosítva", + password: "Jelszó", + password_explain: "Add meg a jelszót, amivel majd dekódolhatod a tárhelyet", + retype_password: "Jelszó megerősítése", + passwords_do_not_match: "A megadott jelszavak különböznek!", + encrypt_storage: "Tárhely titkosítása", + lightning_settings: "Lightning Beállítások", lightning_settings_explain: - 'Saját LND-csomóponthoz való csatlakozáshoz telepítsd az LndHub-ot' + - ' és írd be az URL-ét alul. Hagyd üresen, ha a Veles Wallet saját LNDHub-jához (lndhub.io) szeretnél csatlakozni.' + - ' A beállítások mentése után, minden újonnan létrehozott tárca a megadott LDNHubot fogja használni.', - save: 'Ment', - about: 'Egyéb', - language: 'Nyelv', - currency: 'Valuta', - advanced_options: 'Haladó Beállítások', - enable_advanced_mode: 'Halandó mód bekapcsolása', + "Saját LND-csomóponthoz való csatlakozáshoz telepítsd az LndHub-ot" + + " és írd be az URL-ét alul. Hagyd üresen, ha a Veles Wallet saját LNDHub-jához (lndhub.io) szeretnél csatlakozni." + + " A beállítások mentése után, minden újonnan létrehozott tárca a megadott LDNHubot fogja használni.", + save: "Ment", + about: "Egyéb", + language: "Nyelv", + currency: "Valuta", + advanced_options: "Haladó Beállítások", + enable_advanced_mode: "Halandó mód bekapcsolása" }, plausibledeniability: { - title: 'Elfogadható tagadhatóság', + title: "Elfogadható tagadhatóság", help: - 'Bizonyos körülmények között arra kényszerülhetsz, hogy megadd' + - 'a jelszavadat. A pénzed biztonsága érdekében a Veles Wallettel létrehozhatsz egy ' + - 'alternatív titkosított tárhelyet, alternatív jelszóval. Kényszer hatása alatt ' + - 'megadhatod az alternatív jelszavadat, ami után a Veles Wallet az alternatív ' + - 'tárhelyedet fogja megnyitni. Ez ugyanúgy fog kinézni, mint egy igazi tárhely, ' + - 'azzal a különbséggel, hogy a pénzed teljes biztonságban lesz az elsődleges ' + - 'tárhelyen.', - help2: 'Az alternatív tárhely teljesen működőképes, és akár egy kisebb összeget is elhelyezhetsz rajta, hogy hitelesebbnek tűnjön.', - create_fake_storage: 'Hamis tárhely létrehozása', - go_back: 'Vissza', - create_password: 'Jelszó létrehozása', - create_password_explanation: 'A hamis tárhely jelszava nem lehet ugyanaz, mint az igazi tárhelyé', - password_should_not_match: 'A hamis tárhely jelszava nem lehet ugyanaz, mint az igazi tárhelyé', - retype_password: 'Jelszó megerősítése', - passwords_do_not_match: 'A megadott jelszavak különböznek!', - success: 'Hamis tárhely létrehozva!', + "Bizonyos körülmények között arra kényszerülhetsz, hogy megadd" + + "a jelszavadat. A pénzed biztonsága érdekében a Veles Wallettel létrehozhatsz egy " + + "alternatív titkosított tárhelyet, alternatív jelszóval. Kényszer hatása alatt " + + "megadhatod az alternatív jelszavadat, ami után a Veles Wallet az alternatív " + + "tárhelyedet fogja megnyitni. Ez ugyanúgy fog kinézni, mint egy igazi tárhely, " + + "azzal a különbséggel, hogy a pénzed teljes biztonságban lesz az elsődleges " + + "tárhelyen.", + help2: + "Az alternatív tárhely teljesen működőképes, és akár egy kisebb összeget is elhelyezhetsz rajta, hogy hitelesebbnek tűnjön.", + create_fake_storage: "Hamis tárhely létrehozása", + go_back: "Vissza", + create_password: "Jelszó létrehozása", + create_password_explanation: + "A hamis tárhely jelszava nem lehet ugyanaz, mint az igazi tárhelyé", + password_should_not_match: + "A hamis tárhely jelszava nem lehet ugyanaz, mint az igazi tárhelyé", + retype_password: "Jelszó megerősítése", + passwords_do_not_match: "A megadott jelszavak különböznek!", + success: "Hamis tárhely létrehozva!" }, lnd: { - title: 'kezelés', - choose_source_wallet: 'Válassz forrás tárcát', - refill_lnd_balance: 'Lightning egyenleg feltöltése', - refill: 'Feltölt', - withdraw: 'Pénzkivétel', - expired: 'Lejárt', - placeholder: 'Számla', - sameWalletAsInvoiceError: 'Számlát nem fizethesz be ugyanarról a tárcáról, mint amellyel létrehoztad.', + title: "kezelés", + choose_source_wallet: "Válassz forrás tárcát", + refill_lnd_balance: "Lightning egyenleg feltöltése", + refill: "Feltölt", + withdraw: "Pénzkivétel", + expired: "Lejárt", + placeholder: "Számla", + sameWalletAsInvoiceError: + "Számlát nem fizethesz be ugyanarról a tárcáról, mint amellyel létrehoztad." }, pleasebackup: { - title: 'A tárcád elkészült...', + title: "A tárcád elkészült...", text: - 'Kérlek írd le az alábbi emlékeztető szavakat egy papírlapra, és tedd el egy biztonságos helyre. ' + - 'Ez egy biztonsági mentés, amellyel helyreállíthatod a tárcádat egy másik eszközön.', - ok: 'Rendben, leírtam!', + "Kérlek írd le az alábbi emlékeztető szavakat egy papírlapra, és tedd el egy biztonságos helyre. " + + "Ez egy biztonsági mentés, amellyel helyreállíthatod a tárcádat egy másik eszközön.", + ok: "Rendben, leírtam!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'Ezt a számlát nem fizették ki és lejárt', - has_been_paid: 'Ezt a számlát kifizették', - please_pay: 'Kérlek fizess', - sats: 'sats', - for: 'Cím:', - additional_info: 'További információk', - open_direct_channel: 'Közvetlen csatorna nyitása erre a csomópontra:', - }, + wasnt_paid_and_expired: "Ezt a számlát nem fizették ki és lejárt", + has_been_paid: "Ezt a számlát kifizették", + please_pay: "Kérlek fizess", + sats: "sats", + for: "Cím:", + additional_info: "További információk", + open_direct_channel: "Közvetlen csatorna nyitása erre a csomópontra:" + } }; diff --git a/loc/id_ID.js b/loc/id_ID.js index d78f14a539b..297eb62619c 100644 --- a/loc/id_ID.js +++ b/loc/id_ID.js @@ -1,243 +1,255 @@ module.exports = { _: { - storage_is_encrypted: 'Penyimpanan dienkripsi. Masukkan kata sandi untuk dekripsi:', - enter_password: 'Masukkan kata sandi', - bad_password: 'kata sandi salah, coba lagi', - never: 'tidak pernah', - continue: 'Lanjutkan', - ok: 'OK', + storage_is_encrypted: + "Penyimpanan dienkripsi. Masukkan kata sandi untuk dekripsi:", + enter_password: "Masukkan kata sandi", + bad_password: "kata sandi salah, coba lagi", + never: "tidak pernah", + continue: "Lanjutkan", + ok: "OK" }, wallets: { - select_wallet: 'Pilih dompet', - options: 'Opsi', + select_wallet: "Pilih dompet", + options: "Opsi", createBitcoinWallet: - 'Belum ada dompet bitcoin. Untuk mendanai dompet Lightning, dompet Bitcoin harus dibuat atau diimpor. Yakin ingin melanjutkan?', + "Belum ada dompet bitcoin. Untuk mendanai dompet Lightning, dompet Bitcoin harus dibuat atau diimpor. Yakin ingin melanjutkan?", list: { - app_name: 'Veles Wallet', - title: 'Dompet', - header: 'Sebuah dompet mewakili sepasang kunci rahasia dan sebuah alamat' + 'yang bisa dipilih untuk menerima koin.', - add: 'Tambah dompet', - create_a_wallet: 'Buat dompet', - create_a_wallet1: 'Gratis dan bisa buat', - create_a_wallet2: 'sebanyak yang kamu mau', - latest_transaction: 'transaksi terbaru', - empty_txs1: 'Transaksimu akan muncul di sini,', - empty_txs2: 'saat ini tidak ada transaksi', + app_name: "Veles Wallet", + title: "Dompet", + header: + "Sebuah dompet mewakili sepasang kunci rahasia dan sebuah alamat" + + "yang bisa dipilih untuk menerima koin.", + add: "Tambah dompet", + create_a_wallet: "Buat dompet", + create_a_wallet1: "Gratis dan bisa buat", + create_a_wallet2: "sebanyak yang kamu mau", + latest_transaction: "transaksi terbaru", + empty_txs1: "Transaksimu akan muncul di sini,", + empty_txs2: "saat ini tidak ada transaksi", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Tap di sini untuk membeli bitcoin', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Tap di sini untuk membeli bitcoin" }, reorder: { - title: 'Susun Dompet', + title: "Susun Dompet" }, add: { - title: 'tambah dompet', + title: "tambah dompet", description: - 'Kamu bisa membuat dompet atau memindai paper wallet dalam WIF (Wallet Import Format). Veles Wallet mendukung dompet Segwit.', - scan: 'Pindai', - create: 'Buat', - label_new_segwit: 'Dompet SegWit baru', - label_new_lightning: 'Dompet Lightning baru', - wallet_name: 'nama dompet', - wallet_type: 'tipe', - or: 'atau', - import_wallet: 'Impor dompet', - imported: 'Diimpor', - coming_soon: 'Akan datang', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Kamu bisa membuat dompet atau memindai paper wallet dalam WIF (Wallet Import Format). Veles Wallet mendukung dompet Segwit.", + scan: "Pindai", + create: "Buat", + label_new_segwit: "Dompet SegWit baru", + label_new_lightning: "Dompet Lightning baru", + wallet_name: "nama dompet", + wallet_type: "tipe", + or: "atau", + import_wallet: "Impor dompet", + imported: "Diimpor", + coming_soon: "Akan datang", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Dompet', - address: 'Alamat', - type: 'Tipe', - label: 'Label', - destination: 'tujuan', - description: 'deskripsi', - are_you_sure: 'Yakin?', - yes_delete: 'Ya, hapus', - no_cancel: 'Tidak, batalkan', - delete: 'Hapus', - save: 'Simpan', - delete_this_wallet: 'Hapus dompet ini', - export_backup: 'Ekspor / backup', - buy_bitcoin: 'Beli Bitcoin', - show_xpub: 'Tampilkan XPUB dompet', + title: "Dompet", + address: "Alamat", + type: "Tipe", + label: "Label", + destination: "tujuan", + description: "deskripsi", + are_you_sure: "Yakin?", + yes_delete: "Ya, hapus", + no_cancel: "Tidak, batalkan", + delete: "Hapus", + save: "Simpan", + delete_this_wallet: "Hapus dompet ini", + export_backup: "Ekspor / backup", + buy_bitcoin: "Beli Bitcoin", + show_xpub: "Tampilkan XPUB dompet" }, export: { - title: 'ekspor dompet', + title: "ekspor dompet" }, xpub: { - title: 'XPUB dompet', - copiedToClipboard: 'Disalin ke clipboard.', + title: "XPUB dompet", + copiedToClipboard: "Disalin ke clipboard." }, import: { - title: 'impor', - explanation: 'Ketik kata mnemonic, private key, WIF, atau apapun yang kamu punya. Veles Wallet akan mencoba mengimpor dompet kamu.', - imported: 'Diimpor', - error: 'Gagal mengimpor. Pastikan data yang diketik benar.', - success: 'Berhasil', - do_import: 'Impor', - scan_qr: 'atau mau pindai QR code?', + title: "impor", + explanation: + "Ketik kata mnemonic, private key, WIF, atau apapun yang kamu punya. Veles Wallet akan mencoba mengimpor dompet kamu.", + imported: "Diimpor", + error: "Gagal mengimpor. Pastikan data yang diketik benar.", + success: "Berhasil", + do_import: "Impor", + scan_qr: "atau mau pindai QR code?" }, scanQrWif: { - go_back: 'Kembali', - cancel: 'Batal', - decoding: 'Membaca...', - input_password: 'Masukkan kata sandi', - password_explain: 'Ini adalah private key terenkripsi BIP38', - bad_password: 'kata sandi salah', - wallet_already_exists: 'Dompet sudah ada', - bad_wif: 'WIF salah', - imported_wif: 'WIF diimpor ', - with_address: ' dengan alamat ', - imported_segwit: 'Dompet SegWit diimpor', - imported_legacy: 'Dompet lawas diimpor', - imported_watchonly: 'Alamat tinjauan diimpor', - }, + go_back: "Kembali", + cancel: "Batal", + decoding: "Membaca...", + input_password: "Masukkan kata sandi", + password_explain: "Ini adalah private key terenkripsi BIP38", + bad_password: "kata sandi salah", + wallet_already_exists: "Dompet sudah ada", + bad_wif: "WIF salah", + imported_wif: "WIF diimpor ", + with_address: " dengan alamat ", + imported_segwit: "Dompet SegWit diimpor", + imported_legacy: "Dompet lawas diimpor", + imported_watchonly: "Alamat tinjauan diimpor" + } }, transactions: { list: { - tabBarLabel: 'Transaksi', - title: 'transaksi', - description: 'Daftar transaksi keluar dan masuk dompet', - conf: 'konfirmasi', + tabBarLabel: "Transaksi", + title: "transaksi", + description: "Daftar transaksi keluar dan masuk dompet", + conf: "konfirmasi" }, details: { - title: 'Transaksi', - from: 'Input', - to: 'Output', - copy: 'Salin', - transaction_details: 'Detail transaksi', - show_in_block_explorer: 'Tampilkan di block explorer', - }, + title: "Transaksi", + from: "Input", + to: "Output", + copy: "Salin", + transaction_details: "Detail transaksi", + show_in_block_explorer: "Tampilkan di block explorer" + } }, send: { - header: 'Kirim', + header: "Kirim", details: { - title: 'buat transaksi', - amount_field_is_not_valid: 'Jumlah tidak valid', - fee_field_is_not_valid: 'Tarif tidak valid', - address_field_is_not_valid: 'Alamat tidak valid', - total_exceeds_balance: 'Jumlah yang dikirim melebihi saldo.', - create_tx_error: 'Kesalahan dalam membuat transaksi. Cek kembali alamat tujuan.', - address: 'alamat', - amount_placeholder: 'jumlah (dalam VLS)', - fee_placeholder: 'Tambahan biaya transaksi (dalam VLS)', - note_placeholder: 'catatan pribadi', - cancel: 'Batalkan', - scan: 'Pindai', - send: 'Kirim', - create: 'Buat', - remaining_balance: 'Sisa saldo', + title: "buat transaksi", + amount_field_is_not_valid: "Jumlah tidak valid", + fee_field_is_not_valid: "Tarif tidak valid", + address_field_is_not_valid: "Alamat tidak valid", + total_exceeds_balance: "Jumlah yang dikirim melebihi saldo.", + create_tx_error: + "Kesalahan dalam membuat transaksi. Cek kembali alamat tujuan.", + address: "alamat", + amount_placeholder: "jumlah (dalam VLS)", + fee_placeholder: "Tambahan biaya transaksi (dalam VLS)", + note_placeholder: "catatan pribadi", + cancel: "Batalkan", + scan: "Pindai", + send: "Kirim", + create: "Buat", + remaining_balance: "Sisa saldo" }, confirm: { - header: 'Konfirmasi', - sendNow: 'Kirim sekarang', + header: "Konfirmasi", + sendNow: "Kirim sekarang" }, success: { - done: 'Selesai', + done: "Selesai" }, create: { - details: 'Detail', - title: 'buat transaksi', - error: 'Tidak bisa membuat transaksi. Cek alamat atau jumlah transfer.', - go_back: 'Kembali', - this_is_hex: 'Ini adalah hex transaksi, siap untuk disiarkan ke jaringan.', - to: 'Ke', - amount: 'Jumlah', - fee: 'Tarif', - tx_size: 'Ukuran TX', - satoshi_per_byte: 'Satoshi per byte', - memo: 'Memo', - broadcast: 'Siarkan', - not_enough_fee: 'Tarif tidak cukup. Naikkan tarif', - }, + details: "Detail", + title: "buat transaksi", + error: "Tidak bisa membuat transaksi. Cek alamat atau jumlah transfer.", + go_back: "Kembali", + this_is_hex: + "Ini adalah hex transaksi, siap untuk disiarkan ke jaringan.", + to: "Ke", + amount: "Jumlah", + fee: "Tarif", + tx_size: "Ukuran TX", + satoshi_per_byte: "Satoshi per byte", + memo: "Memo", + broadcast: "Siarkan", + not_enough_fee: "Tarif tidak cukup. Naikkan tarif" + } }, receive: { - header: 'Terima', + header: "Terima", details: { - title: 'Bagikan alamat ini ke pengirim', - share: 'bagikan', - copiedToClipboard: 'Disalin ke clipboard.', - label: 'Deskripsi', - create: 'Buat', - setAmount: 'Terima sejumlah', + title: "Bagikan alamat ini ke pengirim", + share: "bagikan", + copiedToClipboard: "Disalin ke clipboard.", + label: "Deskripsi", + create: "Buat", + setAmount: "Terima sejumlah" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Beli bitcoin', - tap_your_address: 'Untuk menyalin, tap alamat:', - copied: 'Disalin ke Clipboard!', + header: "Beli bitcoin", + tap_your_address: "Untuk menyalin, tap alamat:", + copied: "Disalin ke Clipboard!" }, settings: { - header: 'setting', - plausible_deniability: 'Plausible deniability...', - storage_not_encrypted: 'Penyimpanan: tidak terenkripsi', - storage_encrypted: 'Penyimpanan: terenkripsi', - password: 'kata sandi', - password_explain: 'Buat kata sandi untuk dekripsi penyimpanan', - retype_password: 'Ulangi kata sandi', - passwords_do_not_match: 'Kata sandi tidak cocok', - encrypt_storage: 'Enkripsi penyimpanan', - lightning_settings: 'Pengaturan Lightning', + header: "setting", + plausible_deniability: "Plausible deniability...", + storage_not_encrypted: "Penyimpanan: tidak terenkripsi", + storage_encrypted: "Penyimpanan: terenkripsi", + password: "kata sandi", + password_explain: "Buat kata sandi untuk dekripsi penyimpanan", + retype_password: "Ulangi kata sandi", + passwords_do_not_match: "Kata sandi tidak cocok", + encrypt_storage: "Enkripsi penyimpanan", + lightning_settings: "Pengaturan Lightning", lightning_settings_explain: - 'Pasang LndHub untuk menghubungkan ke node LND kamu' + - ' dan masukkan URL di sini. Biarkan kosong untuk menghubungkan ke LndHub standar (lndhub.io)', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'simpan', - about: 'Tentang', - language: 'Bahasa', - currency: 'Mata Uang', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Pasang LndHub untuk menghubungkan ke node LND kamu" + + " dan masukkan URL di sini. Biarkan kosong untuk menghubungkan ke LndHub standar (lndhub.io)", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "simpan", + about: "Tentang", + language: "Bahasa", + currency: "Mata Uang", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Plausible Deniability', + title: "Plausible Deniability", help: - 'Under certain circumstances, you might be forced to disclose a ' + - 'password. To keep your coins safe, Veles Wallet can create another ' + - 'encrypted storage, with a different password. Under pressure, ' + - 'you can disclose this password to a 3rd party. If entered in ' + + "Under certain circumstances, you might be forced to disclose a " + + "password. To keep your coins safe, Veles Wallet can create another " + + "encrypted storage, with a different password. Under pressure, " + + "you can disclose this password to a 3rd party. If entered in " + "Veles Wallet, it will unlock new 'fake' storage. This will seem " + - 'legit to a 3rd party, but will secretly keep your main storage ' + - 'with coins safe.', - help2: 'New storage will be fully functional, and you can store some ' + 'minimum amounts there so it looks more believable.', - create_fake_storage: 'Create fake encrypted storage', - go_back: 'Go Back', - create_password: 'Create a password', - create_password_explanation: 'Password for fake storage should not match password for your main storage', - password_should_not_match: 'Password for fake storage should not match password for your main storage', - retype_password: 'Retype password', - passwords_do_not_match: 'Passwords do not match, try again', - success: 'Success', + "legit to a 3rd party, but will secretly keep your main storage " + + "with coins safe.", + help2: + "New storage will be fully functional, and you can store some " + + "minimum amounts there so it looks more believable.", + create_fake_storage: "Create fake encrypted storage", + go_back: "Go Back", + create_password: "Create a password", + create_password_explanation: + "Password for fake storage should not match password for your main storage", + password_should_not_match: + "Password for fake storage should not match password for your main storage", + retype_password: "Retype password", + passwords_do_not_match: "Passwords do not match, try again", + success: "Success" }, lnd: { - title: 'atur dana', - choose_source_wallet: 'Pilih dompet sumber', - refill_lnd_balance: 'Isi ulang saldo Lightning', - refill: 'Isi ulang', - withdraw: 'Tarik', - placeholder: 'Invoice', - expired: 'Kadaluarsa', - sameWalletAsInvoiceError: 'Kamu tidak bisa membayar invoice dengan dompet yang sama yang dipakai untuk membuat invoice.', + title: "atur dana", + choose_source_wallet: "Pilih dompet sumber", + refill_lnd_balance: "Isi ulang saldo Lightning", + refill: "Isi ulang", + withdraw: "Tarik", + placeholder: "Invoice", + expired: "Kadaluarsa", + sameWalletAsInvoiceError: + "Kamu tidak bisa membayar invoice dengan dompet yang sama yang dipakai untuk membuat invoice." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/index.js b/loc/index.js index 703f374d686..f483c410956 100644 --- a/loc/index.js +++ b/loc/index.js @@ -1,11 +1,13 @@ -import Localization from 'react-localization'; -import AsyncStorage from '@react-native-community/async-storage'; -import { AppStorage } from '../class'; -import { BitcoinUnit } from '../models/bitcoinUnits'; -import relativeTime from 'dayjs/plugin/relativeTime'; -const dayjs = require('dayjs'); -const currency = require('../currency'); -const BigNumber = require('bignumber.js'); +import Localization from "react-localization"; +import AsyncStorage from "@react-native-community/async-storage"; +import { AppStorage } from "../class"; +import { BitcoinUnit } from "../models/bitcoinUnits"; +import relativeTime from "dayjs/plugin/relativeTime"; + +const dayjs = require("dayjs"); +const currency = require("../currency"); +const BigNumber = require("bignumber.js"); + let strings; dayjs.extend(relativeTime); @@ -13,125 +15,125 @@ dayjs.extend(relativeTime); (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'); + let lang = await AsyncStorage.getItem("lang"); if (lang) { strings.setLanguage(lang); let localeForDayJSAvailable = true; switch (lang) { - case 'el': - require('dayjs/locale/el'); + case "el": + require("dayjs/locale/el"); break; - case 'it': - require('dayjs/locale/it'); + case "it": + require("dayjs/locale/it"); break; - case 'zh_cn': - lang = 'zh-cn'; - require('dayjs/locale/zh-cn'); + case "zh_cn": + lang = "zh-cn"; + require("dayjs/locale/zh-cn"); break; - case 'zh_tw': - lang = 'zh-tw'; - require('dayjs/locale/zh-tw'); + case "zh_tw": + lang = "zh-tw"; + require("dayjs/locale/zh-tw"); break; - case 'ru': - require('dayjs/locale/ru'); + case "ru": + require("dayjs/locale/ru"); break; - case 'es': - require('dayjs/locale/es'); + case "es": + require("dayjs/locale/es"); break; - case 'fi_fi': - require('dayjs/locale/fi'); + case "fi_fi": + require("dayjs/locale/fi"); break; - case 'fr_fr': - require('dayjs/locale/fr'); + case "fr_fr": + require("dayjs/locale/fr"); break; - case 'pt_br': - lang = 'pt-br'; - require('dayjs/locale/pt-br'); + case "pt_br": + lang = "pt-br"; + require("dayjs/locale/pt-br"); break; - case 'pt_pt': - lang = 'pt'; - require('dayjs/locale/pt'); + case "pt_pt": + lang = "pt"; + require("dayjs/locale/pt"); break; - case 'jp_jp': - lang = 'ja'; - require('dayjs/locale/ja'); + case "jp_jp": + lang = "ja"; + require("dayjs/locale/ja"); break; - case 'de_de': - require('dayjs/locale/de'); + case "de_de": + require("dayjs/locale/de"); break; - case 'th_th': - require('dayjs/locale/th'); + case "th_th": + require("dayjs/locale/th"); break; - case 'da_dk': - require('dayjs/locale/da'); + case "da_dk": + require("dayjs/locale/da"); break; - case 'nl_nl': - require('dayjs/locale/nl'); + case "nl_nl": + require("dayjs/locale/nl"); break; - case 'hr_hr': - require('dayjs/locale/hr'); + case "hr_hr": + require("dayjs/locale/hr"); break; - case 'hu_hu': - require('dayjs/locale/hu'); + case "hu_hu": + require("dayjs/locale/hu"); break; - case 'id_id': - require('dayjs/locale/id'); + case "id_id": + require("dayjs/locale/id"); break; - case 'sv_se': - require('dayjs/locale/sv'); + case "sv_se": + require("dayjs/locale/sv"); break; - case 'nb_no': - require('dayjs/locale/nb'); + case "nb_no": + require("dayjs/locale/nb"); break; - case 'tr_tr': - require('dayjs/locale/tr'); + case "tr_tr": + require("dayjs/locale/tr"); break; - case 'vi_vn': - require('dayjs/locale/vi'); + case "vi_vn": + require("dayjs/locale/vi"); break; - case 'ko_KR': - lang = 'ko'; - require('dayjs/locale/ko'); + case "ko_KR": + lang = "ko"; + require("dayjs/locale/ko"); break; default: localeForDayJSAvailable = false; break; } if (localeForDayJSAvailable) { - dayjs.locale(lang.split('_')[0]); + dayjs.locale(lang.split("_")[0]); } } })(); strings = new Localization({ - en: require('./en.js'), - ru: require('./ru.js'), - pt_br: require('./pt_BR.js'), - pt_pt: require('./pt_PT.js'), - es: require('./es.js'), - it: require('./it.js'), - el: require('./el.js'), - ua: require('./ua.js'), - jp_jp: require('./jp_JP.js'), - de_de: require('./de_DE.js'), - da_dk: require('./da_DK.js'), - cs_cz: require('./cs_CZ.js'), - th_th: require('./th_TH.js'), - nl_nl: require('./nl_NL.js'), - fi_fi: require('./fi_FI.js'), - fr_fr: require('./fr_FR.js'), - hr_hr: require('./hr_HR.js'), - hu_hu: require('./hu_HU.js'), - id_id: require('./id_ID.js'), - zh_cn: require('./zh_cn.js'), - zh_tw: require('./zh_tw.js'), - sv_se: require('./sv_SE.js'), - nb_no: require('./nb_NO.js'), - tr_tr: require('./tr_TR.js'), - vi_vn: require('./vi_VN.js'), - zar_xho: require('./ZAR_Xho.js'), - zar_afr: require('./ZAR_Afr.js'), - ko_kr: require('./ko_KR.js'), + en: require("./en.js"), + ru: require("./ru.js"), + pt_br: require("./pt_BR.js"), + pt_pt: require("./pt_PT.js"), + es: require("./es.js"), + it: require("./it.js"), + el: require("./el.js"), + ua: require("./ua.js"), + jp_jp: require("./jp_JP.js"), + de_de: require("./de_DE.js"), + da_dk: require("./da_DK.js"), + cs_cz: require("./cs_CZ.js"), + th_th: require("./th_TH.js"), + nl_nl: require("./nl_NL.js"), + fi_fi: require("./fi_FI.js"), + fr_fr: require("./fr_FR.js"), + hr_hr: require("./hr_HR.js"), + hu_hu: require("./hu_HU.js"), + id_id: require("./id_ID.js"), + zh_cn: require("./zh_cn.js"), + zh_tw: require("./zh_tw.js"), + sv_se: require("./sv_SE.js"), + nb_no: require("./nb_NO.js"), + tr_tr: require("./tr_TR.js"), + vi_vn: require("./vi_VN.js"), + zar_xho: require("./ZAR_Xho.js"), + zar_afr: require("./ZAR_Afr.js"), + ko_kr: require("./ko_KR.js") }); strings.saveLanguage = lang => AsyncStorage.setItem(AppStorage.LANG, lang); @@ -144,7 +146,7 @@ strings.transactionTimeToReadable = time => { try { timejs = dayjs(time).format("YYYY-MM-DD, HH:mm:ss"); } catch (_) { - console.warn('incorrect locale set for dayjs'); + console.warn("incorrect locale set for dayjs"); return time; } return timejs; @@ -153,10 +155,13 @@ strings.transactionTimeToReadable = time => { function removeTrailingZeros(value) { value = value.toString(); - if (value.indexOf('.') === -1) { + if (value.indexOf(".") === -1) { return value; } - while ((value.slice(-1) === '0' || value.slice(-1) === '.') && value.indexOf('.') !== -1) { + while ( + (value.slice(-1) === "0" || value.slice(-1) === ".") && + value.indexOf(".") !== -1 + ) { value = value.substr(0, value.length - 1); } return value; @@ -170,20 +175,24 @@ function removeTrailingZeros(value) { */ strings.formatBalance = (balance, toUnit, withFormatting = false) => { if (toUnit === undefined) { - return balance + ' ' + BitcoinUnit.BTC; + return balance + " " + BitcoinUnit.BTC; } if (toUnit === BitcoinUnit.BTC) { const value = new BigNumber(balance).dividedBy(100000000).toFixed(8); - return removeTrailingZeros(value) + ' ' + BitcoinUnit.BTC; + return removeTrailingZeros(value) + " " + BitcoinUnit.BTC; } else if (toUnit === BitcoinUnit.SATS) { return ( - (balance < 0 ? '-' : '') + - (withFormatting ? new Intl.NumberFormat().format(balance.toString()).replace(/[^0-9]/g, ' ') : balance) + - ' ' + + (balance < 0 ? "-" : "") + + (withFormatting + ? new Intl.NumberFormat() + .format(balance.toString()) + .replace(/[^0-9]/g, " ") + : balance) + + " " + BitcoinUnit.SATS ); } else if (toUnit === BitcoinUnit.LOCAL_CURRENCY) { - return ' '; + return " "; //return currency.satoshiToLocalCurrency(balance); } }; @@ -194,7 +203,11 @@ strings.formatBalance = (balance, toUnit, withFormatting = false) => { * @param toUnit {String} Value from models/bitcoinUnits.js * @returns {string} */ -strings.formatBalanceWithoutSuffix = (balance = 0, toUnit, withFormatting = false) => { +strings.formatBalanceWithoutSuffix = ( + balance = 0, + toUnit, + withFormatting = false +) => { if (toUnit === undefined) { return balance; } @@ -203,9 +216,14 @@ strings.formatBalanceWithoutSuffix = (balance = 0, toUnit, withFormatting = fals const value = new BigNumber(balance).dividedBy(100000000).toFixed(8); return removeTrailingZeros(value); } else if (toUnit === BitcoinUnit.SATS) { - return (balance < 0 ? '-' : '') + (withFormatting ? new Intl.NumberFormat().format(balance).replace(/[^0-9]/g, ' ') : balance); + return ( + (balance < 0 ? "-" : "") + + (withFormatting + ? new Intl.NumberFormat().format(balance).replace(/[^0-9]/g, " ") + : balance) + ); } else if (toUnit === BitcoinUnit.LOCAL_CURRENCY) { - return ' '; + return " "; //return currency.satoshiToLocalCurrency(balance); } } diff --git a/loc/it.js b/loc/it.js index d8539f0881a..85676779a78 100644 --- a/loc/it.js +++ b/loc/it.js @@ -1,246 +1,258 @@ module.exports = { _: { - storage_is_encrypted: 'Il tuo archivio è criptato. È necessaria una password per decriptarlo', - enter_password: 'Inserisci password', - bad_password: 'Password errata, riprova', - never: 'mai', - continue: 'Continua', - ok: 'OK', + storage_is_encrypted: + "Il tuo archivio è criptato. È necessaria una password per decriptarlo", + enter_password: "Inserisci password", + bad_password: "Password errata, riprova", + never: "mai", + continue: "Continua", + ok: "OK" }, wallets: { - select_wallet: 'Seleziona Portafoglio', - options: 'Opzioni', + select_wallet: "Seleziona Portafoglio", + options: "Opzioni", createBitcoinWallet: - 'Non hai un portafoglio Bitcoin attualmente. Per ricaricare un portafoglio Lightning, è necessario creare o importare un portafoglio Bitcoin. Vuoi continuare lo stesso?', + "Non hai un portafoglio Bitcoin attualmente. Per ricaricare un portafoglio Lightning, è necessario creare o importare un portafoglio Bitcoin. Vuoi continuare lo stesso?", list: { - app_name: 'Veles Wallet', - title: 'Portafogli', + app_name: "Veles Wallet", + title: "Portafogli", header: - 'Un portafoglio rappresenta la coppia fra un segreto (chiave privata) e un indirizzo' + - 'che puoi condividere per ricevere Bitcoin.', - add: 'Aggiungi Portafoglio', - create_a_wallet: 'Crea un portafoglio', - create_a_wallet1: 'È gratuito e puoi crearne', - create_a_wallet2: 'quanti ne vuoi', - latest_transaction: 'Transazioni recenti', - empty_txs1: 'Le tue transazioni appariranno qui,', - empty_txs2: 'Nessuna transazione', + "Un portafoglio rappresenta la coppia fra un segreto (chiave privata) e un indirizzo" + + "che puoi condividere per ricevere Bitcoin.", + add: "Aggiungi Portafoglio", + create_a_wallet: "Crea un portafoglio", + create_a_wallet1: "È gratuito e puoi crearne", + create_a_wallet2: "quanti ne vuoi", + latest_transaction: "Transazioni recenti", + empty_txs1: "Le tue transazioni appariranno qui,", + empty_txs2: "Nessuna transazione", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Clicca qui per comprare Bitcoin', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Clicca qui per comprare Bitcoin" }, reorder: { - title: 'Riordina Portafogli', + title: "Riordina Portafogli" }, add: { - title: 'Aggiungi Portafoglio', + title: "Aggiungi Portafoglio", description: - 'Puoi scansionare il Backup di un Paper-Wallet (in WIF - Wallet Import Format), o creare un nuovo portafoglio. I portafogli Segwit sono supportati di default.', - scan: 'Scan', - create: 'Crea', - label_new_segwit: 'Nuovo SegWit', - label_new_lightning: 'Nuovo Lightning', - wallet_name: 'Nome Portafoglio', - wallet_type: 'Tipo', - or: 'o', - import_wallet: 'Importa Portafoglio', - imported: 'Importato', - coming_soon: 'In arrivo', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Puoi scansionare il Backup di un Paper-Wallet (in WIF - Wallet Import Format), o creare un nuovo portafoglio. I portafogli Segwit sono supportati di default.", + scan: "Scan", + create: "Crea", + label_new_segwit: "Nuovo SegWit", + label_new_lightning: "Nuovo Lightning", + wallet_name: "Nome Portafoglio", + wallet_type: "Tipo", + or: "o", + import_wallet: "Importa Portafoglio", + imported: "Importato", + coming_soon: "In arrivo", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Portafoglio', - address: 'Indirizzo', - type: 'Tipo', - label: 'Etichetta', - destination: 'Destinazione', - description: 'Descrizione', - are_you_sure: 'Sei sicuro?', - yes_delete: 'Si, elimina', - no_cancel: 'No, annulla', - delete: 'Elimina', - save: 'Salva', - delete_this_wallet: 'Elimina questo portafoglio', - export_backup: 'Esporta / Backup', - buy_bitcoin: 'Compra Bitcoin', - show_xpub: 'Mostra XPUB del portafoglio', + title: "Portafoglio", + address: "Indirizzo", + type: "Tipo", + label: "Etichetta", + destination: "Destinazione", + description: "Descrizione", + are_you_sure: "Sei sicuro?", + yes_delete: "Si, elimina", + no_cancel: "No, annulla", + delete: "Elimina", + save: "Salva", + delete_this_wallet: "Elimina questo portafoglio", + export_backup: "Esporta / Backup", + buy_bitcoin: "Compra Bitcoin", + show_xpub: "Mostra XPUB del portafoglio" }, export: { - title: 'Esporta portafoglio', + title: "Esporta portafoglio" }, xpub: { - title: 'XPUB del Portafoglio', - copiedToClipboard: 'Copiata negli appunti.', + title: "XPUB del Portafoglio", + copiedToClipboard: "Copiata negli appunti." }, import: { - title: 'Importa', + title: "Importa", explanation: - 'Scrivi qui la tua frase mnemonica, chiave privata, WIF, o qualunque altra cosa tu abbia. Veles Wallet tenterà di indovinare il formato corretto e importerà il tuo portafoglio', - imported: 'Importato', - error: 'Importazione fallita. Assicurati che le informazioni fornite siano valide.', - success: 'Fatto', - do_import: 'Importa', - scan_qr: 'o scansionare un codice QR?', + "Scrivi qui la tua frase mnemonica, chiave privata, WIF, o qualunque altra cosa tu abbia. Veles Wallet tenterà di indovinare il formato corretto e importerà il tuo portafoglio", + imported: "Importato", + error: + "Importazione fallita. Assicurati che le informazioni fornite siano valide.", + success: "Fatto", + do_import: "Importa", + scan_qr: "o scansionare un codice QR?" }, scanQrWif: { - go_back: 'Indietro', - cancel: 'Annulla', - decoding: 'Decodifica', - input_password: 'Inserisci password', - password_explain: 'Questa è una chiave privata BIP38 criptata', - bad_password: 'Password errata', - wallet_already_exists: 'Questo portafoglio esiste già', - bad_wif: 'WIF errato', - imported_wif: 'Importa WIF ', - with_address: ' con indirizzo ', - imported_segwit: 'SegWit importato', - imported_legacy: 'Legacy importato', - imported_watchonly: 'Watch-only importato', - }, + go_back: "Indietro", + cancel: "Annulla", + decoding: "Decodifica", + input_password: "Inserisci password", + password_explain: "Questa è una chiave privata BIP38 criptata", + bad_password: "Password errata", + wallet_already_exists: "Questo portafoglio esiste già", + bad_wif: "WIF errato", + imported_wif: "Importa WIF ", + with_address: " con indirizzo ", + imported_segwit: "SegWit importato", + imported_legacy: "Legacy importato", + imported_watchonly: "Watch-only importato" + } }, transactions: { list: { - tabBarLabel: 'Transazioni', - title: 'Transazioni', - description: 'Una lista delle transazioni in entrata e in uscita dei tuoi portafogli', - conf: 'conf', + tabBarLabel: "Transazioni", + title: "Transazioni", + description: + "Una lista delle transazioni in entrata e in uscita dei tuoi portafogli", + conf: "conf" }, details: { - title: 'Transazione', - from: 'Da', - to: 'A', - copy: 'Copia', - transaction_details: 'Dettagli transazione', - show_in_block_explorer: 'Mostra sul block explorer', - }, + title: "Transazione", + from: "Da", + to: "A", + copy: "Copia", + transaction_details: "Dettagli transazione", + show_in_block_explorer: "Mostra sul block explorer" + } }, send: { - header: 'Invia', + header: "Invia", details: { - title: 'Crea transazione', - amount_field_is_not_valid: 'Importo non valido', - fee_field_is_not_valid: 'Commissione non valida', - address_field_is_not_valid: 'Indirizzo non valido', + title: "Crea transazione", + amount_field_is_not_valid: "Importo non valido", + fee_field_is_not_valid: "Commissione non valida", + address_field_is_not_valid: "Indirizzo non valido", total_exceeds_balance: "L'importo da inviare eccede i fondi disponibili.", - create_tx_error: "Si è verificato un errore nella creazione della transazione. Assicurati che l'indirizzo sia valido", - address: 'Indirizzo', - amount_placeholder: 'Importo da inviare (in VLS)', - fee_placeholder: 'Più commissione (in VLS)', - note_placeholder: 'Nota', - cancel: 'Annulla', - scan: 'Scansiona', - send: 'Invia', - create: 'Crea', - remaining_balance: 'Fondi rimanenti', + create_tx_error: + "Si è verificato un errore nella creazione della transazione. Assicurati che l'indirizzo sia valido", + address: "Indirizzo", + amount_placeholder: "Importo da inviare (in VLS)", + fee_placeholder: "Più commissione (in VLS)", + note_placeholder: "Nota", + cancel: "Annulla", + scan: "Scansiona", + send: "Invia", + create: "Crea", + remaining_balance: "Fondi rimanenti" }, confirm: { - header: 'Conferma', - sendNow: 'Invia ora', + header: "Conferma", + sendNow: "Invia ora" }, success: { - done: 'Fatto', + done: "Fatto" }, create: { - details: 'Dettagli', - title: 'Crea transazione', - error: 'Errore nella creazione della transazione. Indirizzo o importo invalido', - go_back: 'Indietro', - this_is_hex: "Questo è l'hex della transazione, firmato e pronto per essere trasmesso sulla rete.", - to: 'A', - amount: 'Importo', - fee: 'Commissione', - tx_size: 'Grandezza TX', - satoshi_per_byte: 'Satoshi per byte', - memo: 'Memo', - broadcast: 'Trasmetti', - not_enough_fee: 'Commissione non sufficiente. Aumenta la commissione', - }, + details: "Dettagli", + title: "Crea transazione", + error: + "Errore nella creazione della transazione. Indirizzo o importo invalido", + go_back: "Indietro", + this_is_hex: + "Questo è l'hex della transazione, firmato e pronto per essere trasmesso sulla rete.", + to: "A", + amount: "Importo", + fee: "Commissione", + tx_size: "Grandezza TX", + satoshi_per_byte: "Satoshi per byte", + memo: "Memo", + broadcast: "Trasmetti", + not_enough_fee: "Commissione non sufficiente. Aumenta la commissione" + } }, receive: { - header: 'Ricevi', + header: "Ricevi", details: { title: "Condividi questo indirizzo con l'acquirente", - share: 'Condividi', - copiedToClipboard: 'Copiato negli appunti.', - label: 'Descrizione', - create: 'Crea', - setAmount: 'Ricevi con importo', + share: "Condividi", + copiedToClipboard: "Copiato negli appunti.", + label: "Descrizione", + create: "Crea", + setAmount: "Ricevi con importo" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Compra Bitcoin', - tap_your_address: 'Clicca sul tuo indirizzo per copiarlo negli appunti:', - copied: 'Copiato negli appunti!', + header: "Compra Bitcoin", + tap_your_address: "Clicca sul tuo indirizzo per copiarlo negli appunti:", + copied: "Copiato negli appunti!" }, settings: { - header: 'Impostazioni', - plausible_deniability: 'Negazione plausibile...', - storage_not_encrypted: 'Archivio: non criptato', - storage_encrypted: 'Archivio: criptato', - password: 'Password', + header: "Impostazioni", + plausible_deniability: "Negazione plausibile...", + storage_not_encrypted: "Archivio: non criptato", + storage_encrypted: "Archivio: criptato", + password: "Password", password_explain: "Crea la password che userai per decriptare l'archivio", - retype_password: 'Reinserisci password', - passwords_do_not_match: 'Le password non corrispondono', - encrypt_storage: 'Cripta archivio', - lightning_settings: 'Impostazioni Lightning', + retype_password: "Reinserisci password", + passwords_do_not_match: "Le password non corrispondono", + encrypt_storage: "Cripta archivio", + lightning_settings: "Impostazioni Lightning", lightning_settings_explain: - 'Per connetterti al tuo nodo LND personale installa LndHub' + - ' e inserisci il suo URL qui nelle impostazioni. Lascialo vuoto per utilizzare il nodo LndHub di default (lndhub.io)', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Salva', - about: 'Informazioni', - language: 'Lingua', - currency: 'Valuta', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Per connetterti al tuo nodo LND personale installa LndHub" + + " e inserisci il suo URL qui nelle impostazioni. Lascialo vuoto per utilizzare il nodo LndHub di default (lndhub.io)", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Salva", + about: "Informazioni", + language: "Lingua", + currency: "Valuta", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Negazione Plausibile', + title: "Negazione Plausibile", help: - 'In alcune circostanze, potresti essere costretto a rivelare la ' + - 'password. Per mantenere i tuoi Bitcoin al sicuro, Veles Wallet può creare un altro ' + - 'archivio criptato, con una password diversa. Se costretto, ' + - 'puoi rivelare questa password alle terze parti. Se inserita in ' + + "In alcune circostanze, potresti essere costretto a rivelare la " + + "password. Per mantenere i tuoi Bitcoin al sicuro, Veles Wallet può creare un altro " + + "archivio criptato, con una password diversa. Se costretto, " + + "puoi rivelare questa password alle terze parti. Se inserita in " + 'Veles Wallet, questa sbloccherà un "falso" archivio. Esso sembrerà ' + - 'autentico alle terze parti, ma manterrà segretamente il tuo archivio principale ' + - 'con i Bitcoin al sicuro.', - help2: 'Il nuovo archivio sarà completamente funzionante, e puoi conservarci ' + 'piccole quantità così sembrerà più credibile.', - create_fake_storage: 'Crea archivio falso criptato', - go_back: 'Indietro', - create_password: 'Crea una password', - create_password_explanation: "La password per l'archivio falso non deve corrispondere a quella dell'archivio principale", - password_should_not_match: "La password per l'archivio falso non deve corrispondere a quella dell'archivio principale", - retype_password: 'Reinserisci password', - passwords_do_not_match: 'Le password non corrispondono, riprova', - success: 'Fatto', + "autentico alle terze parti, ma manterrà segretamente il tuo archivio principale " + + "con i Bitcoin al sicuro.", + help2: + "Il nuovo archivio sarà completamente funzionante, e puoi conservarci " + + "piccole quantità così sembrerà più credibile.", + create_fake_storage: "Crea archivio falso criptato", + go_back: "Indietro", + create_password: "Crea una password", + create_password_explanation: + "La password per l'archivio falso non deve corrispondere a quella dell'archivio principale", + password_should_not_match: + "La password per l'archivio falso non deve corrispondere a quella dell'archivio principale", + retype_password: "Reinserisci password", + passwords_do_not_match: "Le password non corrispondono, riprova", + success: "Fatto" }, lnd: { - title: 'Gestisci fondi', - choose_source_wallet: 'Scegli un portafoglio sorgente', - refill_lnd_balance: 'Ricarica saldo del portafoglio Lightning', - refill: 'Ricarica', - withdraw: 'Preleva', - expired: 'Scaduto', - placeholder: 'Fattura', - sameWalletAsInvoiceError: 'Non puoi pagare una fattura con lo stesso portafoglio utilizzato per crearla.', + title: "Gestisci fondi", + choose_source_wallet: "Scegli un portafoglio sorgente", + refill_lnd_balance: "Ricarica saldo del portafoglio Lightning", + refill: "Ricarica", + withdraw: "Preleva", + expired: "Scaduto", + placeholder: "Fattura", + sameWalletAsInvoiceError: + "Non puoi pagare una fattura con lo stesso portafoglio utilizzato per crearla." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/jp_JP.js b/loc/jp_JP.js index 4f888ef1e23..6eeca87d3fa 100644 --- a/loc/jp_JP.js +++ b/loc/jp_JP.js @@ -1,20 +1,23 @@ module.exports = { _: { - storage_is_encrypted: "ウォレットは暗号化されています。復号にはパスワードが必要です。", + storage_is_encrypted: + "ウォレットは暗号化されています。復号にはパスワードが必要です。", enter_password: "パスワードを入力", bad_password: "パスワードが間違っています。", never: "データなし", continue: "続行", - ok: "OK", + ok: "OK" }, wallets: { select_wallet: "ウォレット選択", options: "オプション", - createBitcoinWallet: "Bitcoin ウォレットを持っていません。Lightning ウォレットへ課金する場合は Bitcoin ウォレットを新規作成するかインポートする必要があります。続行しますか?", + createBitcoinWallet: + "Bitcoin ウォレットを持っていません。Lightning ウォレットへ課金する場合は Bitcoin ウォレットを新規作成するかインポートする必要があります。続行しますか?", list: { app_name: "Veles Wallet", title: "ウォレット", - header: "ウォレットは秘密鍵(プライベートキー)とウォレットアドレスのペアで構成されています。コインを受信するために共有できます。", + header: + "ウォレットは秘密鍵(プライベートキー)とウォレットアドレスのペアで構成されています。コインを受信するために共有できます。", add: "ウォレットの追加", create_a_wallet: "ウォレットの作成", create_a_wallet1: "ウォレット作成は無料で", @@ -22,16 +25,19 @@ module.exports = { latest_transaction: "最新の取引", empty_txs1: "ここに取引が表示されます", empty_txs2: "現在は何もありません", - empty_txs1_lightning: "Lightning ウォレットを日常の取引にご利用ください。手数料は安く、送金はあっという間に完了します。", - empty_txs2_lightning: "\n利用を開始するには\"資金の管理\"をタップしてウォレットへ送金してください。", - tap_here_to_buy: "Bitcoin を購入するにはここをタップ", + empty_txs1_lightning: + "Lightning ウォレットを日常の取引にご利用ください。手数料は安く、送金はあっという間に完了します。", + empty_txs2_lightning: + '\n利用を開始するには"資金の管理"をタップしてウォレットへ送金してください。', + tap_here_to_buy: "Bitcoin を購入するにはここをタップ" }, reorder: { - title: "ウォレットの並び替え", + title: "ウォレットの並び替え" }, add: { title: "ウォレットの追加", - description: "ペーパーウォレット(WIF 形式- Wallet Import Format)をスキャンするかウォレットを新規作成できます。既定で Segwit ウォレットが作成されます。", + description: + "ペーパーウォレット(WIF 形式- Wallet Import Format)をスキャンするかウォレットを新規作成できます。既定で Segwit ウォレットが作成されます。", scan: "読取り", create: "作成", label_new_segwit: "新規 SegWit", @@ -43,7 +49,7 @@ module.exports = { imported: "インポート完了", coming_soon: "準備中", lightning: "Lightning", - bitcoin: "Veles", + bitcoin: "Veles" }, details: { title: "ウォレット", @@ -60,23 +66,25 @@ module.exports = { delete_this_wallet: "このウォレットの削除", export_backup: "エクスポート / バックアップ", buy_bitcoin: "Bitcoin の購入", - show_xpub: "ウォレット XPUB の表示", + show_xpub: "ウォレット XPUB の表示" }, export: { - title: "ウォレットのエクスポート", + title: "ウォレットのエクスポート" }, xpub: { title: "ウォレット XPUB", - copiedToClipboard: "クリップボードにコピーしました。", + copiedToClipboard: "クリップボードにコピーしました。" }, import: { title: "インポート", - explanation: "ここにニーモニック、秘密鍵(プライベートキー)、WIFなどを入力してください。Veles Wallet が正しい形式を推測しウォレットをインポートします。", + explanation: + "ここにニーモニック、秘密鍵(プライベートキー)、WIFなどを入力してください。Veles Wallet が正しい形式を推測しウォレットをインポートします。", imported: "インポート完了", - error: "インポートに失敗しました。入力したデータが有効か確認してください。", + error: + "インポートに失敗しました。入力したデータが有効か確認してください。", success: "成功", do_import: "インポート", - scan_qr: "QR コードの読み取り", + scan_qr: "QR コードの読み取り" }, scanQrWif: { go_back: "戻る", @@ -91,15 +99,15 @@ module.exports = { with_address: "アドレス", imported_segwit: "SegWit インポート完了", imported_legacy: "Legacy インポート完了", - imported_watchonly: "閲覧専用 インポート完了", - }, + imported_watchonly: "閲覧専用 インポート完了" + } }, transactions: { list: { tabBarLabel: "取引", title: "取引", description: "ウォレットの送金または入金のリスト", - conf: "確認", + conf: "確認" }, details: { title: "取引", @@ -107,20 +115,21 @@ module.exports = { to: "送り先", copy: "コピー", transaction_details: "取引詳細", - show_in_block_explorer: "Block Explorer で表示", - }, + show_in_block_explorer: "Block Explorer で表示" + } }, send: { header: "送金", success: { - done: "完了", + done: "完了" }, details: { title: "取引の作成", amount_field_is_not_valid: "金額欄が正しくありません", fee_field_is_not_valid: "手数料欄が正しくありません", address_field_is_not_valid: "アドレス欄が正しくありません", - create_tx_error: "取引作成中にエラーが発生しました。有効な送金アドレスか確認してください。", + create_tx_error: + "取引作成中にエラーが発生しました。有効な送金アドレスか確認してください。", address: "アドレス", amount_placeholder: "送金額 (VLS)", fee_placeholder: "取引手数料 (VLS)", @@ -130,16 +139,17 @@ module.exports = { send: "送金", create: "作成", remaining_balance: "残高", - total_exceeds_balance: "送金額が利用可能残高を超えています。", + total_exceeds_balance: "送金額が利用可能残高を超えています。" }, confirm: { header: "確認", - sendNow: "送金実行", + sendNow: "送金実行" }, create: { title: "詳細", details: "取引作成", - error: "取引作成でエラーが発生しました。アドレスまたは送金額を確認してください。", + error: + "取引作成でエラーが発生しました。アドレスまたは送金額を確認してください。", go_back: "戻る", this_is_hex: "署名されネットワークへ送信される 16 進数取引コードです", to: "送金先", @@ -149,8 +159,8 @@ module.exports = { satoshi_per_byte: "Satoshi(サトシ)/1バイト", memo: "メモ", broadcast: "送信", - not_enough_fee: "手数料不足です。増額してください", - }, + not_enough_fee: "手数料不足です。増額してください" + } }, receive: { header: "入金", @@ -160,14 +170,14 @@ module.exports = { copiedToClipboard: "クリップボードにコピーしました。", label: "概要", create: "作成", - setAmount: "入金額", + setAmount: "入金額" }, - scan_lnurl: "スキャンして受信", + scan_lnurl: "スキャンして受信" }, buyBitcoin: { header: "Bitcoin の購入", tap_your_address: "タップしてアドレスをクリップボードにコピー", - copied: "クリップボードにコピーしました!", + copied: "クリップボードにコピーしました!" }, settings: { header: "設定", @@ -187,20 +197,24 @@ module.exports = { language: "言語", currency: "通貨", advanced_options: "詳細オプション", - enable_advanced_mode: "詳細モードを有効にする", + enable_advanced_mode: "詳細モードを有効にする" }, plausibledeniability: { title: "拒否権", - help: "BuleWallet のウォレットの復号に必要なパスワードを第三者に強要される場合、コインを安全に保護するためにメインのウォレットとは異なるパスワードで 暗号化されたダミーのウォレットを作成することが可能です。第三者へ異なるパスワードを提供すれば、Veles Wallet のダミーの 暗号化ウォレットを復号することとなり、メインのウォレットは隠匿され コインは安全に保護されます。", - help2: "新規のダミーのウォレットはメインと同様に機能します。少額のコインを入金しておくことで ダミーと疑われないようにすることが可能です。", + help: + "BuleWallet のウォレットの復号に必要なパスワードを第三者に強要される場合、コインを安全に保護するためにメインのウォレットとは異なるパスワードで 暗号化されたダミーのウォレットを作成することが可能です。第三者へ異なるパスワードを提供すれば、Veles Wallet のダミーの 暗号化ウォレットを復号することとなり、メインのウォレットは隠匿され コインは安全に保護されます。", + help2: + "新規のダミーのウォレットはメインと同様に機能します。少額のコインを入金しておくことで ダミーと疑われないようにすることが可能です。", create_fake_storage: "ダミーの暗号化ウォレットの作成", go_back: "戻る", create_password: "パスワードの作成", - create_password_explanation: "ダミーのウォレットのパスワードはメインのウォレットのパスワードと異なる必要があります。", - password_should_not_match: "ダミーのウォレットのパスワードはメインのウォレットのパスワードと異なる必要があります。", + create_password_explanation: + "ダミーのウォレットのパスワードはメインのウォレットのパスワードと異なる必要があります。", + password_should_not_match: + "ダミーのウォレットのパスワードはメインのウォレットのパスワードと異なる必要があります。", retype_password: "パスワードの再入力", passwords_do_not_match: "パスワードが一致しません", - success: "成功", + success: "成功" }, lnd: { title: "資金の管理", @@ -210,20 +224,23 @@ module.exports = { withdraw: "引き出し", placeholder: "入金依頼", expired: "失効", - sameWalletAsInvoiceError: "以前作成したウォレットと同じウォレットへの支払いはできません。", + sameWalletAsInvoiceError: + "以前作成したウォレットと同じウォレットへの支払いはできません。" }, pleasebackup: { title: "ウォレットを作成しています...", - text: "すべてのニーモニックを別紙に書きとめてください。他のデバイスへウォレットをリストアする際にニモニックが必要になります。デスクトップ用ウォレットの Electrum wallet (https//electrum.org/) へニーモニックを使用してウォレットをリストアすることが可能です。", - ok: "すべてのニーモニックを書きとめました", + text: + "すべてのニーモニックを別紙に書きとめてください。他のデバイスへウォレットをリストアする際にニモニックが必要になります。デスクトップ用ウォレットの Electrum wallet (https//electrum.org/) へニーモニックを使用してウォレットをリストアすることが可能です。", + ok: "すべてのニーモニックを書きとめました" }, lndViewInvoice: { - wasnt_paid_and_expired: "この請求書は支払いが行われなかったため無効になりました", + wasnt_paid_and_expired: + "この請求書は支払いが行われなかったため無効になりました", has_been_paid: "この請求書は支払い完了しました", please_pay: "支払う額", sats: "sats", for: "メモ", additional_info: "追加情報", - open_direct_channel: "このノードの直接チャネルを作成", - }, + open_direct_channel: "このノードの直接チャネルを作成" + } }; diff --git a/loc/ko_KR.js b/loc/ko_KR.js index c85bb8a1bb5..b88258c2e96 100644 --- a/loc/ko_KR.js +++ b/loc/ko_KR.js @@ -1,20 +1,23 @@ module.exports = { _: { - storage_is_encrypted: "고객님의 저장소가 암호화 되었습니다. 암호화 해제시 비밀번호 입력이 요구됩니다.", + storage_is_encrypted: + "고객님의 저장소가 암호화 되었습니다. 암호화 해제시 비밀번호 입력이 요구됩니다.", enter_password: "비밀번호를 입력해 주세요.", bad_password: "잘못된 비밀번호입니다. 다시 입력해 주세요.", never: "사용 불가한 상태입니다.", continue: "계속하기", - ok: "확인", + ok: "확인" }, wallets: { select_wallet: "지갑 선택", options: "옵션", - createBitcoinWallet: "현재 비트코인 지갑을 보유하고 있지 않습니다. 라이트닝 지갑에 이체하기 위해선 비트코인 지갑의 생성 또는 들여오기가 필요합니다. 계속해서 진행하시겠습니까?", + createBitcoinWallet: + "현재 비트코인 지갑을 보유하고 있지 않습니다. 라이트닝 지갑에 이체하기 위해선 비트코인 지갑의 생성 또는 들여오기가 필요합니다. 계속해서 진행하시겠습니까?", list: { app_name: "Veles Wallet", title: "지갑", - header: "지갑은 한 쌍의 암호키 (개인 키)와 코인 수령을 위해 공유될 수 있는 지갑 주소를 제공합니다. ", + header: + "지갑은 한 쌍의 암호키 (개인 키)와 코인 수령을 위해 공유될 수 있는 지갑 주소를 제공합니다. ", add: "지갑 추가", create_a_wallet: "지갑 생성", create_a_wallet1: "무료로 생성할 수 있습니다.", @@ -22,16 +25,19 @@ module.exports = { latest_transaction: "최신 거래", empty_txs1: "거래가 이 곳에 나타날 것입니다. ", empty_txs2: "현재 아무 표시 없음", - empty_txs1_lightning: "라이트닝 지갑은 일상적인 거래에 사용됩니다. 수수료가 비교적 저렴하며, 속도가 상당히 빠릅니다.", - empty_txs2_lightning: "\"자금 관리\"를 눌러 사용하시고 고객님의 잔고를 충전하세요.", - tap_here_to_buy: "비트코인 구매를 위해 이곳을 눌러주세요.", + empty_txs1_lightning: + "라이트닝 지갑은 일상적인 거래에 사용됩니다. 수수료가 비교적 저렴하며, 속도가 상당히 빠릅니다.", + empty_txs2_lightning: + '"자금 관리"를 눌러 사용하시고 고객님의 잔고를 충전하세요.', + tap_here_to_buy: "비트코인 구매를 위해 이곳을 눌러주세요." }, reorder: { - title: "지갑 재정렬하기", + title: "지갑 재정렬하기" }, add: { title: "지갑 추가하기", - description: "백업 종이 지갑 스캔 ( WIF - Wallet Import Format) 또는 새로운 지갑을 생성할 수 있습니다. Segwit 지갑은 기본값으로 지원됩니다.", + description: + "백업 종이 지갑 스캔 ( WIF - Wallet Import Format) 또는 새로운 지갑을 생성할 수 있습니다. Segwit 지갑은 기본값으로 지원됩니다.", scan: "스캔하기", create: "생성하기", label_new_segwit: "새로운 SegWit 생성하기", @@ -43,7 +49,7 @@ module.exports = { imported: "들여오기 완료", coming_soon: "Coming Soon", lightning: "라이트닝", - bitcoin: "Veles", + bitcoin: "Veles" }, details: { title: "지갑", @@ -60,23 +66,24 @@ module.exports = { delete_this_wallet: "지갑 삭제하기", export_backup: "내보내기/ 백업", buy_bitcoin: "비트코인 구매하기", - show_xpub: "지갑 XPUB 표시하기", + show_xpub: "지갑 XPUB 표시하기" }, export: { - title: "지갑 내보내기", + title: "지갑 내보내기" }, xpub: { title: "지갑 XPUB", - copiedToClipboard: "클립보드에 복사되었습니다.", + copiedToClipboard: "클립보드에 복사되었습니다." }, import: { title: "들여오기", - explanation: "연상 기호문, 개인 키, WIF 등의 모든 것을 이곳에 입력해 주세요. 블루웰럿이 최적의 포맷과 지갑 들여오기를 도와드립니다.", + explanation: + "연상 기호문, 개인 키, WIF 등의 모든 것을 이곳에 입력해 주세요. 블루웰럿이 최적의 포맷과 지갑 들여오기를 도와드립니다.", imported: "들여오기 완료", error: "들여오기 실패. 입력된 정보의 유효함을 확인해 주세요.", success: "완료", do_import: "들여오기", - scan_qr: "QR 코드 스캔으로 대신하겠습니까?", + scan_qr: "QR 코드 스캔으로 대신하겠습니까?" }, scanQrWif: { go_back: "뒤로 가기", @@ -91,15 +98,15 @@ module.exports = { with_address: "주소와 함께", imported_segwit: "SegWit 들여오기 완료", imported_legacy: "레거시 들여오기 완료", - imported_watchonly: "읽기 전용 들여오기 완료", - }, + imported_watchonly: "읽기 전용 들여오기 완료" + } }, transactions: { list: { tabBarLabel: "거래 목록", title: "거래 목록", description: "고객님 지갑의 입송금 거래 내역", - conf: "conf", + conf: "conf" }, details: { title: "거래", @@ -107,20 +114,21 @@ module.exports = { to: "에게", copy: "복사하기", transaction_details: "거래 세부 내역", - show_in_block_explorer: "블록 탐색자에서 보기", - }, + show_in_block_explorer: "블록 탐색자에서 보기" + } }, send: { header: "전송하기;", success: { - done: "완료", + done: "완료" }, details: { title: "거래 생성하기", amount_field_is_not_valid: "금액 입력란이 유효하지 않습니다.", fee_field_is_not_valid: "수수료 입력란이 유효하지 않습니다.", address_field_is_not_valid: "주소 입력란이 유효하지 않습니다.", - create_tx_error: "거래 생성 오류가 발생했습니다. 유효한 주소를 입력해 주세요.", + create_tx_error: + "거래 생성 오류가 발생했습니다. 유효한 주소를 입력해 주세요.", address: "주소", amount_placeholder: "송금 금액 (VLS)", fee_placeholder: "추가 거래 수수료 (VLS)", @@ -130,18 +138,19 @@ module.exports = { send: "전송하기", create: "인보이스 생성하기", remaining_balance: "보유 잔액", - total_exceeds_balance: "송금 금액이 이용 가능한 잔액보다 큽니다.", + total_exceeds_balance: "송금 금액이 이용 가능한 잔액보다 큽니다." }, confirm: { header: "승인하기", - sendNow: "지금 전송하기", + sendNow: "지금 전송하기" }, create: { details: "상세 내역", title: "거래 생성하기", error: "거래 생성 에러 발생. 유효하지 않은 주소 또는 송금 금액?", go_back: "뒤로 가기", - this_is_hex: "해당 거래는 서명되었으며, 네트워크로 송출될 hex 거래입니다.", + this_is_hex: + "해당 거래는 서명되었으며, 네트워크로 송출될 hex 거래입니다.", to: "에게", amount: "금액", fee: "수수료", @@ -149,8 +158,8 @@ module.exports = { satoshi_per_byte: "바이트 당 사토시", memo: "메모", broadcast: "송출하기", - not_enough_fee: "수수료가 충분하지 않습니다. 수수료를 늘려주세요.", - }, + not_enough_fee: "수수료가 충분하지 않습니다. 수수료를 늘려주세요." + } }, receive: { header: "수령하기", @@ -160,14 +169,14 @@ module.exports = { copiedToClipboard: "클립보드에 복사되었습니다.", label: "상세 내역", create: "생성하기", - setAmount: "금액 수령하기", + setAmount: "금액 수령하기" }, - scan_lnurl: "수령을 위해 스캔하기", + scan_lnurl: "수령을 위해 스캔하기" }, buyBitcoin: { header: "비트코인 구매하기", tap_your_address: "클립보드에 복사하기 위해 고객님의 주소를 눌러주세요.", - copied: "클립보드에 복사되었습니다!", + copied: "클립보드에 복사되었습니다!" }, settings: { header: "세팅", @@ -187,20 +196,25 @@ module.exports = { language: "언어", currency: "통화", advanced_options: "고급 옵션", - enable_advanced_mode: "고급 모드 사용하기", + enable_advanced_mode: "고급 모드 사용하기" }, plausibledeniability: { title: "입력 생략", - help: "특정한 상황에 고객님께서 비밀번호를 공개에 대한 요구를 받을 수도 있습니다. 고객님의 코인을 안전히 보관하기 위하여, 블루웰렛은 다른 비밀번호에 연동된 또 다른 암호화 저장소를 생성할 수 있습니다. 제 3자에 해당 비밀번호가 노출될 수 있으며, 블루웰렛에 비밀번호 입력시 새로운 모조 저장소가 잠금 해제됩니다. 이것이 제 3자에겐 고객님의 저장소에 접근한 것처럼 보입니다. 그러나 고객님의 코인이 보관된 메인 저장소는 비밀리에 안전하게 보존됩니다.", - help2: "새로운 저장소가 정상적으로 작동될 것입니다. 최소한의 금액을 보관하여 더욱 믿을 수 있는 저장소임을 확인하세요. ", + help: + "특정한 상황에 고객님께서 비밀번호를 공개에 대한 요구를 받을 수도 있습니다. 고객님의 코인을 안전히 보관하기 위하여, 블루웰렛은 다른 비밀번호에 연동된 또 다른 암호화 저장소를 생성할 수 있습니다. 제 3자에 해당 비밀번호가 노출될 수 있으며, 블루웰렛에 비밀번호 입력시 새로운 모조 저장소가 잠금 해제됩니다. 이것이 제 3자에겐 고객님의 저장소에 접근한 것처럼 보입니다. 그러나 고객님의 코인이 보관된 메인 저장소는 비밀리에 안전하게 보존됩니다.", + help2: + "새로운 저장소가 정상적으로 작동될 것입니다. 최소한의 금액을 보관하여 더욱 믿을 수 있는 저장소임을 확인하세요. ", create_fake_storage: "암호화된 모조 저장소 생성하기", go_back: "뒤로 가기", create_password: "비밀번호 생성하기", - create_password_explanation: "모조 저장소의 비밀번호가 고객님의 메인 저장소의 비밀번호와 일치하지 않습니다.", - password_should_not_match: "모조 저장소의 비밀번호가 고객님의 메인 저장소의 비밀번호와 일치하지 않습니다.", + create_password_explanation: + "모조 저장소의 비밀번호가 고객님의 메인 저장소의 비밀번호와 일치하지 않습니다.", + password_should_not_match: + "모조 저장소의 비밀번호가 고객님의 메인 저장소의 비밀번호와 일치하지 않습니다.", retype_password: "비밀번호를 다시 입력해 주시기 바랍니다.", - passwords_do_not_match: "비밀번호가 일치하지 않습니다. 다시 입력해 주시기 바랍니다.", - success: "완료", + passwords_do_not_match: + "비밀번호가 일치하지 않습니다. 다시 입력해 주시기 바랍니다.", + success: "완료" }, lnd: { title: "자금 관리하기", @@ -210,12 +224,14 @@ module.exports = { withdraw: "출금하기", placeholder: "송장", expired: "만료", - sameWalletAsInvoiceError: "인보이스 생성에 사용된 지갑으로 해당 인보이스를 지불할 수 없습니다.", + sameWalletAsInvoiceError: + "인보이스 생성에 사용된 지갑으로 해당 인보이스를 지불할 수 없습니다." }, pleasebackup: { title: "고객님의 지갑이 생성되었습니다...", - text: "연상 기호문을 받아 적어주시기 바랍니다. 해당 연상 기호문은 다른 장치에 지갑을 복구하는 백업으로 사용됩니다.", - ok: "네, 기호문을 다른 곳에 옮겨 적었습니다.", + text: + "연상 기호문을 받아 적어주시기 바랍니다. 해당 연상 기호문은 다른 장치에 지갑을 복구하는 백업으로 사용됩니다.", + ok: "네, 기호문을 다른 곳에 옮겨 적었습니다." }, lndViewInvoice: { wasnt_paid_and_expired: "해당 인보이스는 지불되지 않았으며 만료되었습니다.", @@ -224,6 +240,6 @@ module.exports = { sats: "사토시", for: "에 대한", additional_info: "추가 정보", - open_direct_channel: "해당 노드로 다이렉트 채널 열기", - }, + open_direct_channel: "해당 노드로 다이렉트 채널 열기" + } }; diff --git a/loc/nb_NO.js b/loc/nb_NO.js index fc603ebcb24..c56a7c5fa83 100644 --- a/loc/nb_NO.js +++ b/loc/nb_NO.js @@ -1,244 +1,261 @@ module.exports = { _: { - storage_is_encrypted: 'Lagringen din er kryptert. Passord er nødvendig for å dekryptere det', - enter_password: 'Oppgi passord', - bad_password: 'Feil passord, prøv igjen', - never: 'aldri', - continue: 'Fortsett', - ok: 'OK', + storage_is_encrypted: + "Lagringen din er kryptert. Passord er nødvendig for å dekryptere det", + enter_password: "Oppgi passord", + bad_password: "Feil passord, prøv igjen", + never: "aldri", + continue: "Fortsett", + ok: "OK" }, wallets: { - select_wallet: 'Velg Lommebok', - options: 'innstillinger', + select_wallet: "Velg Lommebok", + options: "innstillinger", createBitcoinWallet: - 'Du har ingen Bitcoin-lommebok. For å finansiere en Lightning-lommebok, må en Bitcoin-lommebok være opprettet eller importert. Vil du fortsette uansett?', + "Du har ingen Bitcoin-lommebok. For å finansiere en Lightning-lommebok, må en Bitcoin-lommebok være opprettet eller importert. Vil du fortsette uansett?", list: { - app_name: 'Veles Wallet', - title: 'lommebøker', - header: 'En lommebok representerer en hemmelighet (privat nøkkel) og en adresse ' + ' du kan dele for å motta kryptovaluta.', - add: 'Legg til lommebok', - create_a_wallet: 'Lag en lommebok', - create_a_wallet1: 'Det er gratis, og du kan lage', - create_a_wallet2: 'så mange du vil', - latest_transaction: 'siste transaksjonen', - empty_txs1: 'Dine transaksjoner vil vises her,', - empty_txs2: 'ingen for øyeblikket', + app_name: "Veles Wallet", + title: "lommebøker", + header: + "En lommebok representerer en hemmelighet (privat nøkkel) og en adresse " + + " du kan dele for å motta kryptovaluta.", + add: "Legg til lommebok", + create_a_wallet: "Lag en lommebok", + create_a_wallet1: "Det er gratis, og du kan lage", + create_a_wallet2: "så mange du vil", + latest_transaction: "siste transaksjonen", + empty_txs1: "Dine transaksjoner vil vises her,", + empty_txs2: "ingen for øyeblikket", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Trykk her for å kjøpe Bitcoin', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Trykk her for å kjøpe Bitcoin" }, reorder: { - title: 'Omorganisere lommebøker', + title: "Omorganisere lommebøker" }, add: { - title: 'legg til lommebok', + title: "legg til lommebok", description: - 'Du kan enten skanne en backup papirlommebok (i WIF - Wallet Import Format), eller opprett en ny lommebok. Segwit lommebøker støttes som standard.', - scan: 'Skann', - create: 'Lag', - label_new_segwit: 'Ny SegWit', - label_new_lightning: 'Ny Lightning', - wallet_name: 'navn', - wallet_type: 'type', - or: 'eller', - import_wallet: 'Importer lommeboken', - imported: 'Importert', - coming_soon: 'Kommer snart', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Du kan enten skanne en backup papirlommebok (i WIF - Wallet Import Format), eller opprett en ny lommebok. Segwit lommebøker støttes som standard.", + scan: "Skann", + create: "Lag", + label_new_segwit: "Ny SegWit", + label_new_lightning: "Ny Lightning", + wallet_name: "navn", + wallet_type: "type", + or: "eller", + import_wallet: "Importer lommeboken", + imported: "Importert", + coming_soon: "Kommer snart", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Lommebok', - address: 'Adresse', - type: 'Type', - label: 'Merkelapp', - destination: 'mål', - description: 'beskrivelse', - are_you_sure: 'Er du sikker?', - yes_delete: 'Ja, slett', - no_cancel: 'Nei, avbryt', - delete: 'Slett', - save: 'Lagre', - delete_this_wallet: 'Slett denne lommeboken', - export_backup: 'Eksporter / backup', - buy_bitcoin: 'Kjøp Bitcoin', - show_xpub: 'Vis lommebok XPUB', + title: "Lommebok", + address: "Adresse", + type: "Type", + label: "Merkelapp", + destination: "mål", + description: "beskrivelse", + are_you_sure: "Er du sikker?", + yes_delete: "Ja, slett", + no_cancel: "Nei, avbryt", + delete: "Slett", + save: "Lagre", + delete_this_wallet: "Slett denne lommeboken", + export_backup: "Eksporter / backup", + buy_bitcoin: "Kjøp Bitcoin", + show_xpub: "Vis lommebok XPUB" }, export: { - title: 'lommebok eksport', + title: "lommebok eksport" }, xpub: { - title: 'lommebok XPUB', - copiedToClipboard: 'Kopiert til utklippstavlen.', + title: "lommebok XPUB", + copiedToClipboard: "Kopiert til utklippstavlen." }, import: { - title: 'importer', + title: "importer", explanation: - 'Skriv her din mnemonic, private nøkkel, WIF, eller hva som helst annet. Veles Wallet vil gjøre sitt beste for å gjette riktig format og importere lommeboken din', - imported: 'importert', - error: 'Kunne ikke importere. Vennligst vær sikker på at de oppgitte dataene er gyldige.', - success: 'Suksess', - do_import: 'Importer', - scan_qr: 'eller skann QR-kode i stedet?', + "Skriv her din mnemonic, private nøkkel, WIF, eller hva som helst annet. Veles Wallet vil gjøre sitt beste for å gjette riktig format og importere lommeboken din", + imported: "importert", + error: + "Kunne ikke importere. Vennligst vær sikker på at de oppgitte dataene er gyldige.", + success: "Suksess", + do_import: "Importer", + scan_qr: "eller skann QR-kode i stedet?" }, scanQrWif: { - go_back: 'Gå tilbake', - cancel: 'Avbryt', - decoding: 'Dekoder', - input_password: 'Input passord', - password_explain: 'Dette er BIP38 kryptert privat nøkkel', - bad_password: 'Feil passord', - wallet_already_exists: 'En slik lommebok eksisterer allerede', - bad_wif: 'Dårlig WIF', - imported_wif: 'Importert WIF', - with_address: ' med adresse', - imported_segwit: 'Importert SegWit', - imported_legacy: 'Importert Legacy', - imported_watchonly: 'Importert Watch-only', - }, + go_back: "Gå tilbake", + cancel: "Avbryt", + decoding: "Dekoder", + input_password: "Input passord", + password_explain: "Dette er BIP38 kryptert privat nøkkel", + bad_password: "Feil passord", + wallet_already_exists: "En slik lommebok eksisterer allerede", + bad_wif: "Dårlig WIF", + imported_wif: "Importert WIF", + with_address: " med adresse", + imported_segwit: "Importert SegWit", + imported_legacy: "Importert Legacy", + imported_watchonly: "Importert Watch-only" + } }, transactions: { list: { - tabBarLabel: 'Transaksjoner', - title: 'transaksjoner', - description: 'En liste over inngående eller utgående transaksjoner fra lommebokene dine', - conf: 'conf', + tabBarLabel: "Transaksjoner", + title: "transaksjoner", + description: + "En liste over inngående eller utgående transaksjoner fra lommebokene dine", + conf: "conf" }, details: { - title: 'Transaksjon', - from: 'Input', - to: 'Produksjon', - copy: 'Kopiere', - transaction_details: 'Transaksjonsdetaljer', - show_in_block_explorer: 'Vis i blokkutforsker', - }, + title: "Transaksjon", + from: "Input", + to: "Produksjon", + copy: "Kopiere", + transaction_details: "Transaksjonsdetaljer", + show_in_block_explorer: "Vis i blokkutforsker" + } }, send: { - header: 'Sende', + header: "Sende", details: { - title: 'opprett transaksjon', - amount_field_is_not_valid: 'Beløp feltet er ikke gyldig', - fee_field_is_not_valid: 'Avgiftsfeltet er ikke gyldig', - address_field_is_not_valid: 'Adressefeltet er ikke gyldig', - total_exceeds_balance: 'Sendingsbeløpet overstiger den tilgjengelige saldoen.', - create_tx_error: 'Det oppsto en feil under opprettelse av transaksjonen. Vennligst vær sikker på at adressen er gyldig.', - address: 'adresse', - amount_placeholder: 'mengde å sende (i VLS)', - fee_placeholder: 'pluss transaksjonsgebyr (i VLS)', - note_placeholder: 'notat til meg selv', - cancel: 'Avbryt', - scan: 'Skanne', - send: 'Sende', - create: 'Lag', - remaining_balance: 'Gjenværende balanse', + title: "opprett transaksjon", + amount_field_is_not_valid: "Beløp feltet er ikke gyldig", + fee_field_is_not_valid: "Avgiftsfeltet er ikke gyldig", + address_field_is_not_valid: "Adressefeltet er ikke gyldig", + total_exceeds_balance: + "Sendingsbeløpet overstiger den tilgjengelige saldoen.", + create_tx_error: + "Det oppsto en feil under opprettelse av transaksjonen. Vennligst vær sikker på at adressen er gyldig.", + address: "adresse", + amount_placeholder: "mengde å sende (i VLS)", + fee_placeholder: "pluss transaksjonsgebyr (i VLS)", + note_placeholder: "notat til meg selv", + cancel: "Avbryt", + scan: "Skanne", + send: "Sende", + create: "Lag", + remaining_balance: "Gjenværende balanse" }, confirm: { - header: 'Bekrefte', - sendNow: 'Send nå', + header: "Bekrefte", + sendNow: "Send nå" }, success: { - done: 'Ferdig', + done: "Ferdig" }, create: { - details: 'Detaljer', - title: 'opprett transaksjon', - error: 'Feil ved å opprette transaksjon. Ugyldig adresse eller send beløp?', - go_back: 'Gå tilbake', - this_is_hex: 'Dette er transaksjonsheks, signert og klar til å sendes til nettverket.', - to: 'Til', - amount: 'Beløp', - fee: 'Avgift', - tx_size: 'TX-størrelse', - satoshi_per_byte: 'Satoshi per byte', - memo: 'Memo', - broadcast: 'Kringkaste', - not_enough_fee: 'Ikke nok avgift. Øk avgiften', - }, + details: "Detaljer", + title: "opprett transaksjon", + error: + "Feil ved å opprette transaksjon. Ugyldig adresse eller send beløp?", + go_back: "Gå tilbake", + this_is_hex: + "Dette er transaksjonsheks, signert og klar til å sendes til nettverket.", + to: "Til", + amount: "Beløp", + fee: "Avgift", + tx_size: "TX-størrelse", + satoshi_per_byte: "Satoshi per byte", + memo: "Memo", + broadcast: "Kringkaste", + not_enough_fee: "Ikke nok avgift. Øk avgiften" + } }, receive: { - header: 'Motta', + header: "Motta", details: { - title: 'Del denne adressen med betaleren', - share: 'dele', - copiedToClipboard: 'Kopiert til utklippstavlen.', - label: 'Beskrivelse', - create: 'Lag', - setAmount: 'Motta med beløp', + title: "Del denne adressen med betaleren", + share: "dele", + copiedToClipboard: "Kopiert til utklippstavlen.", + label: "Beskrivelse", + create: "Lag", + setAmount: "Motta med beløp" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Kjøp Bitcoin', - tap_your_address: 'Trykk på adressen din for å kopiere den til utklippstavlen:', - copied: 'Kopiert til utklippstavlen!', + header: "Kjøp Bitcoin", + tap_your_address: + "Trykk på adressen din for å kopiere den til utklippstavlen:", + copied: "Kopiert til utklippstavlen!" }, settings: { - header: 'innstillinger', - plausible_deniability: 'Troverdig denibilitet ...', - storage_not_encrypted: 'Lagring: ikke kryptert', - storage_encrypted: 'Lagring: kryptert', - password: 'Passord', - password_explain: 'Opprett passordet du vil bruke til å dekryptere lagringen', - retype_password: 'Skriv inn passordet på nytt', - passwords_do_not_match: 'passordene er ikke like', - encrypt_storage: 'Krypter lagring', - lightning_settings: 'Lightning innstillinger', + header: "innstillinger", + plausible_deniability: "Troverdig denibilitet ...", + storage_not_encrypted: "Lagring: ikke kryptert", + storage_encrypted: "Lagring: kryptert", + password: "Passord", + password_explain: + "Opprett passordet du vil bruke til å dekryptere lagringen", + retype_password: "Skriv inn passordet på nytt", + passwords_do_not_match: "passordene er ikke like", + encrypt_storage: "Krypter lagring", + lightning_settings: "Lightning innstillinger", lightning_settings_explain: - 'For å koble til din egen LND-node, vennligst installer LndHub' + - ' og legg URLen her i innstillinger. La feltet være tomt for å bruke Veles Wallets LNDHub (lndhub.io). Lommebøker opprettet etter lagring av endringer, vil koble til den angitte LNDHub.', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Lagre', - about: 'Om', - language: 'Språk', - currency: 'Valuta', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "For å koble til din egen LND-node, vennligst installer LndHub" + + " og legg URLen her i innstillinger. La feltet være tomt for å bruke Veles Wallets LNDHub (lndhub.io). Lommebøker opprettet etter lagring av endringer, vil koble til den angitte LNDHub.", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Lagre", + about: "Om", + language: "Språk", + currency: "Valuta", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Troverdighet benektelse', + title: "Troverdighet benektelse", help: - 'Under visse omstendigheter kan du bli tvunget til å avsløre en' + - 'passord. For å holde mynten din trygg, kan Veles Wallet opprette en annen' + - 'kryptert lagring, med et annet passord. Under press,' + - 'Du kan oppgi dette passordet til en tredjepart. Hvis inntastet i' + + "Under visse omstendigheter kan du bli tvunget til å avsløre en" + + "passord. For å holde mynten din trygg, kan Veles Wallet opprette en annen" + + "kryptert lagring, med et annet passord. Under press," + + "Du kan oppgi dette passordet til en tredjepart. Hvis inntastet i" + 'Veles Wallet, det vil låse opp ny "falsk" lagring. Dette vil virke' + - 'troverdig overfor en tredje part, men vil i hemmelighet beholde ' + - 'hovedlageret trygt.', - help2: 'Ny lagring vil være fullt funksjonell, og du kan lagre en mindre sum der' + ' , slik at det ser mer troverdig ut.', - create_fake_storage: 'Lag falsk kryptert lagring', - go_back: 'Gå tilbake', - create_password: 'Lag et passord', - create_password_explanation: 'Passord for falsk lagring må ikke matche passord for hovedlager', - password_should_not_match: 'Passord for falsk lagring må ikke matche passord for hovedlager', - retype_password: 'Skriv inn passordet på nytt', - passwords_do_not_match: 'Passordene stemmer ikke overens, prøv igjen', - success: 'Vellykket', + "troverdig overfor en tredje part, men vil i hemmelighet beholde " + + "hovedlageret trygt.", + help2: + "Ny lagring vil være fullt funksjonell, og du kan lagre en mindre sum der" + + " , slik at det ser mer troverdig ut.", + create_fake_storage: "Lag falsk kryptert lagring", + go_back: "Gå tilbake", + create_password: "Lag et passord", + create_password_explanation: + "Passord for falsk lagring må ikke matche passord for hovedlager", + password_should_not_match: + "Passord for falsk lagring må ikke matche passord for hovedlager", + retype_password: "Skriv inn passordet på nytt", + passwords_do_not_match: "Passordene stemmer ikke overens, prøv igjen", + success: "Vellykket" }, lnd: { - title: 'administrere midler', - choose_source_wallet: 'Velg en kilde lommebok', - refill_lnd_balance: 'Refill Lightning lommebokbalanse', - refill: 'Fylle på', - withdraw: 'Ta ut', - expired: 'Utløpt', - placeholder: 'Faktura', - sameWalletAsInvoiceError: 'Du kan ikke betale en faktura med samme lommebok som brukes til å lage den.', + title: "administrere midler", + choose_source_wallet: "Velg en kilde lommebok", + refill_lnd_balance: "Refill Lightning lommebokbalanse", + refill: "Fylle på", + withdraw: "Ta ut", + expired: "Utløpt", + placeholder: "Faktura", + sameWalletAsInvoiceError: + "Du kan ikke betale en faktura med samme lommebok som brukes til å lage den." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/nl_NL.js b/loc/nl_NL.js index 82eba24d5e7..ceb0e4a9eaa 100644 --- a/loc/nl_NL.js +++ b/loc/nl_NL.js @@ -1,247 +1,262 @@ module.exports = { _: { - storage_is_encrypted: 'Uw opslag is versleuteld. Wachtwoord is vereist om het te ontcijferen', - enter_password: 'Voer wachtwoord in', - bad_password: 'Verkeerd wachtwoord, probeer opnieuw', - never: 'nooit', - continue: 'Continue', - ok: 'OK', + storage_is_encrypted: + "Uw opslag is versleuteld. Wachtwoord is vereist om het te ontcijferen", + enter_password: "Voer wachtwoord in", + bad_password: "Verkeerd wachtwoord, probeer opnieuw", + never: "nooit", + continue: "Continue", + ok: "OK" }, wallets: { - select_wallet: 'Selecteer portemonnee', - options: 'opties', + select_wallet: "Selecteer portemonnee", + options: "opties", createBitcoinWallet: - 'Om een Lightning-portemonnee te kunnen gebruiken, is een Bitcoin-portemonnee nodig om deze te financieren. Wil je toch doorgaan?', + "Om een Lightning-portemonnee te kunnen gebruiken, is een Bitcoin-portemonnee nodig om deze te financieren. Wil je toch doorgaan?", list: { - app_name: 'Veles Wallet', - title: 'portemonnees', - header: 'Een portemonnee vertegenwoordigt een geheime (privésleutel) en een adres' + 'dat u kunt delen om munten te ontvangen.', - add: 'Portemonnee toevoegen', - create_a_wallet: 'Portemonnee aanmaken', - create_a_wallet1: 'Het is gratis en u kunt er', - create_a_wallet2: 'zoveel maken als u wilt', - latest_transaction: 'laatste transactie', - empty_txs1: 'Uw transacties verschijnen hier,', - empty_txs2: 'geen transacties op dit moment', + app_name: "Veles Wallet", + title: "portemonnees", + header: + "Een portemonnee vertegenwoordigt een geheime (privésleutel) en een adres" + + "dat u kunt delen om munten te ontvangen.", + add: "Portemonnee toevoegen", + create_a_wallet: "Portemonnee aanmaken", + create_a_wallet1: "Het is gratis en u kunt er", + create_a_wallet2: "zoveel maken als u wilt", + latest_transaction: "laatste transactie", + empty_txs1: "Uw transacties verschijnen hier,", + empty_txs2: "geen transacties op dit moment", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Klik hier om Bitcoin te kopen', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Klik hier om Bitcoin te kopen" }, reorder: { - title: 'Portemonnees opnieuw ordenen', + title: "Portemonnees opnieuw ordenen" }, add: { - title: 'portemonnee toevoegen', + title: "portemonnee toevoegen", description: - 'U kunt een back-up papieren portemonnee scannen (in WIF - Wallet Import Format) of een nieuwe portemonnee maken. Segwit-wallets worden standaard ondersteund.', - scan: 'Scan', - create: 'Aanmaken', - label_new_segwit: 'Nieuwe SegWit', - label_new_lightning: 'Nieuwe Lightning', - wallet_name: 'portemonnee naam', - wallet_type: 'type', - or: 'of', - import_wallet: 'Portemonnee importeren', - imported: 'Geïmporteerd', - coming_soon: 'Komt binnenkort', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "U kunt een back-up papieren portemonnee scannen (in WIF - Wallet Import Format) of een nieuwe portemonnee maken. Segwit-wallets worden standaard ondersteund.", + scan: "Scan", + create: "Aanmaken", + label_new_segwit: "Nieuwe SegWit", + label_new_lightning: "Nieuwe Lightning", + wallet_name: "portemonnee naam", + wallet_type: "type", + or: "of", + import_wallet: "Portemonnee importeren", + imported: "Geïmporteerd", + coming_soon: "Komt binnenkort", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Portemonnee', - address: 'Adres', - type: 'Type', - label: 'Label', - destination: 'bestemming', - description: 'beschrijving', - are_you_sure: 'Weet u het zeker?', - yes_delete: 'Ja, verwijderen', - no_cancel: 'Nee, annuleren', - delete: 'Verwijderen', - save: 'Opslaan', - delete_this_wallet: 'Verwijder deze portemonnee', - export_backup: 'Exporteren / back-up maken', - buy_bitcoin: 'Koop Bitcoin', - show_xpub: 'Toon portemonnee XPUB', + title: "Portemonnee", + address: "Adres", + type: "Type", + label: "Label", + destination: "bestemming", + description: "beschrijving", + are_you_sure: "Weet u het zeker?", + yes_delete: "Ja, verwijderen", + no_cancel: "Nee, annuleren", + delete: "Verwijderen", + save: "Opslaan", + delete_this_wallet: "Verwijder deze portemonnee", + export_backup: "Exporteren / back-up maken", + buy_bitcoin: "Koop Bitcoin", + show_xpub: "Toon portemonnee XPUB" }, export: { - title: 'portemonnee exporteren', + title: "portemonnee exporteren" }, xpub: { - title: 'portemonnee XPUB', - copiedToClipboard: 'Gekopieerd naar het klembord.', + title: "portemonnee XPUB", + copiedToClipboard: "Gekopieerd naar het klembord." }, import: { - title: 'importeren', + title: "importeren", explanation: - 'Schrijf hier uw ezelsbruggetje, privésleutel, WIF, of een ander formaat. Veles Wallet zal zijn best doen om het juiste formaat te raden en uw portemonnee te importeren', - imported: 'Geïmporteerd', - error: 'Importeren mislukt. Zorg ervoor dat de verstrekte gegevens geldig zijn.', - success: 'Succes', - do_import: 'Importeren', - scan_qr: 'of QR-code scannen?', + "Schrijf hier uw ezelsbruggetje, privésleutel, WIF, of een ander formaat. Veles Wallet zal zijn best doen om het juiste formaat te raden en uw portemonnee te importeren", + imported: "Geïmporteerd", + error: + "Importeren mislukt. Zorg ervoor dat de verstrekte gegevens geldig zijn.", + success: "Succes", + do_import: "Importeren", + scan_qr: "of QR-code scannen?" }, scanQrWif: { - go_back: 'Ga terug', - cancel: 'Annuleren', - decoding: 'Decoderen', - input_password: 'Voer wachtwoord in', - password_explain: 'Dit is een BIP38-gecodeerde privésleutel', - bad_password: 'Verkeerd wachtwoord', + go_back: "Ga terug", + cancel: "Annuleren", + decoding: "Decoderen", + input_password: "Voer wachtwoord in", + password_explain: "Dit is een BIP38-gecodeerde privésleutel", + bad_password: "Verkeerd wachtwoord", wallet_already_exists: "Zo'n portemonnee bestaat al", - bad_wif: 'Verkeerde WIF', - imported_wif: 'WIF geïmporteerd ', - with_address: ' met adres ', - imported_segwit: 'SegWit geïmporteerd', - imported_legacy: 'Legacy geïmporteerd', - imported_watchonly: 'Watch-only geïmporteerd', - }, + bad_wif: "Verkeerde WIF", + imported_wif: "WIF geïmporteerd ", + with_address: " met adres ", + imported_segwit: "SegWit geïmporteerd", + imported_legacy: "Legacy geïmporteerd", + imported_watchonly: "Watch-only geïmporteerd" + } }, transactions: { list: { - tabBarLabel: 'Transacties', - title: 'transacties', - description: 'Een lijst met ingaande of uitgaande transacties van uw portemonnee', - conf: 'conf', + tabBarLabel: "Transacties", + title: "transacties", + description: + "Een lijst met ingaande of uitgaande transacties van uw portemonnee", + conf: "conf" }, details: { - title: 'Transacties', - from: 'Invoer', - to: 'Uitgang', - copy: 'Kopiëren', - transaction_details: 'Transactie details', - show_in_block_explorer: 'Weergeven in blokverkenner', - }, + title: "Transacties", + from: "Invoer", + to: "Uitgang", + copy: "Kopiëren", + transaction_details: "Transactie details", + show_in_block_explorer: "Weergeven in blokverkenner" + } }, send: { - header: 'Verstuur', + header: "Verstuur", details: { - title: 'transacties aanmaken', - amount_field_is_not_valid: 'Bedrag veld is niet geldig', - fee_field_is_not_valid: 'Tarief is niet geldig', - address_field_is_not_valid: 'Adresveld is niet geldig', - total_exceeds_balance: 'Het verzendingsbedrag overschrijdt het beschikbare saldo.', - create_tx_error: 'Er is een fout opgetreden bij het maken van de transactie. Zorg ervoor dat het adres geldig is.', - address: 'adres', - amount_placeholder: 'te verzenden bedrag (in VLS)', - fee_placeholder: 'plus transactie vergoeding (in VLS)', - note_placeholder: 'notitie voor mezelf', - cancel: 'Annuleren', - scan: 'Scannen', - send: 'Verzenden', - create: 'Aanmaken', - remaining_balance: 'Resterende saldo', + title: "transacties aanmaken", + amount_field_is_not_valid: "Bedrag veld is niet geldig", + fee_field_is_not_valid: "Tarief is niet geldig", + address_field_is_not_valid: "Adresveld is niet geldig", + total_exceeds_balance: + "Het verzendingsbedrag overschrijdt het beschikbare saldo.", + create_tx_error: + "Er is een fout opgetreden bij het maken van de transactie. Zorg ervoor dat het adres geldig is.", + address: "adres", + amount_placeholder: "te verzenden bedrag (in VLS)", + fee_placeholder: "plus transactie vergoeding (in VLS)", + note_placeholder: "notitie voor mezelf", + cancel: "Annuleren", + scan: "Scannen", + send: "Verzenden", + create: "Aanmaken", + remaining_balance: "Resterende saldo" }, confirm: { - header: 'Bevestig', - sendNow: 'Nu verzenden', + header: "Bevestig", + sendNow: "Nu verzenden" }, success: { - done: 'Klaar', + done: "Klaar" }, create: { - details: 'Details', - title: 'transactie aanmaken', - error: 'Fout bij het maken van transactie. Ongeldig adres of bedrag?', - go_back: 'Ga terug', - this_is_hex: 'Dit is de transactie-hex, ondertekend en klaar om op het netwerk te worden uitgezonden.', - to: 'Naar', - amount: 'Bedrag', - fee: 'Vergoeding', - tx_size: 'TX grootte', - satoshi_per_byte: 'Satoshi per byte', - memo: 'Memo', - broadcast: 'Uitzenden', - not_enough_fee: 'Niet genoeg vergoeding. Verhoog de vergoeding', - }, + details: "Details", + title: "transactie aanmaken", + error: "Fout bij het maken van transactie. Ongeldig adres of bedrag?", + go_back: "Ga terug", + this_is_hex: + "Dit is de transactie-hex, ondertekend en klaar om op het netwerk te worden uitgezonden.", + to: "Naar", + amount: "Bedrag", + fee: "Vergoeding", + tx_size: "TX grootte", + satoshi_per_byte: "Satoshi per byte", + memo: "Memo", + broadcast: "Uitzenden", + not_enough_fee: "Niet genoeg vergoeding. Verhoog de vergoeding" + } }, receive: { - header: 'Ontvang', + header: "Ontvang", details: { - title: 'Deel dit adres met betaler', - share: 'delen', - copiedToClipboard: 'Gekopieerd naar het klembord.', - label: 'Omschrijving', - create: 'Create', - setAmount: 'Ontvang met bedrag', + title: "Deel dit adres met betaler", + share: "delen", + copiedToClipboard: "Gekopieerd naar het klembord.", + label: "Omschrijving", + create: "Create", + setAmount: "Ontvang met bedrag" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Koop Bitcoin', - tap_your_address: 'Tik op uw adres om het naar het klembord te kopiëren:', - copied: 'Gekopieerd naar het klembord!', + header: "Koop Bitcoin", + tap_your_address: "Tik op uw adres om het naar het klembord te kopiëren:", + copied: "Gekopieerd naar het klembord!" }, settings: { - header: 'instellingen', - plausible_deniability: 'Plausibele ontkenning...', - storage_not_encrypted: 'Opslag: niet versleuteld', - storage_encrypted: 'Opslag: versleuteld', - password: 'Wachtwoord', - password_explain: 'Maak een wachtwoord aan dat u wilt gebruiken om de opslag te versleutelen', - retype_password: 'Geef nogmaals het wachtwoord', - passwords_do_not_match: 'Wachtwoorden komen niet overeen', - encrypt_storage: 'Versleutel opslag', - lightning_settings: 'Lightning instellingen', + header: "instellingen", + plausible_deniability: "Plausibele ontkenning...", + storage_not_encrypted: "Opslag: niet versleuteld", + storage_encrypted: "Opslag: versleuteld", + password: "Wachtwoord", + password_explain: + "Maak een wachtwoord aan dat u wilt gebruiken om de opslag te versleutelen", + retype_password: "Geef nogmaals het wachtwoord", + passwords_do_not_match: "Wachtwoorden komen niet overeen", + encrypt_storage: "Versleutel opslag", + lightning_settings: "Lightning instellingen", lightning_settings_explain: - 'Om verbinding te maken met uw eigen LND-knooppunt' + - ' installeert u LndHub en zet u de URL hier in de instellingen. ' + - 'Laat dit leeg om de standaard lndHub (lndhub.io) te gebruiken.', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Opslaan', - about: 'Over', - language: 'Taal', - currency: 'Valuta', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Om verbinding te maken met uw eigen LND-knooppunt" + + " installeert u LndHub en zet u de URL hier in de instellingen. " + + "Laat dit leeg om de standaard lndHub (lndhub.io) te gebruiken.", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Opslaan", + about: "Over", + language: "Taal", + currency: "Valuta", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Plausibele ontkenning', + title: "Plausibele ontkenning", help: - 'Onder bepaalde omstandigheden kunt u worden gedwongen om uw' + - ' wachtwoord te onthullen. Om uw munten veilig te houden, kan ' + - 'Veles Wallet nog een versleutelde opslag aanmaken, met een ander ' + - 'wachtwoord. Onder druk kunt u dit wachtwoord bekendmaken aan ' + - 'de derde partij. Indien ingevoerd in Veles Wallet, zal het nieuwe ' + + "Onder bepaalde omstandigheden kunt u worden gedwongen om uw" + + " wachtwoord te onthullen. Om uw munten veilig te houden, kan " + + "Veles Wallet nog een versleutelde opslag aanmaken, met een ander " + + "wachtwoord. Onder druk kunt u dit wachtwoord bekendmaken aan " + + "de derde partij. Indien ingevoerd in Veles Wallet, 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', + "derde partij, maar zal uw hoofdopslag met munten 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.', - create_fake_storage: 'Nep versleutelde opslag aanmaken', - go_back: 'Ga terug', - create_password: 'Wachtwoord aanmaken', - create_password_explanation: 'Wachtwoord voor nep-opslag hoort niet overeen te komen met wachtwoord voor uw hoofdopslag', - password_should_not_match: 'Wachtwoord voor nep-opslag hoort niet overeen te komen met wachtwoord voor uw hoofdopslag', - retype_password: 'Herhaal wachtwoord', - passwords_do_not_match: 'Wachtwoorden komen niet overeen, probeer het opnieuw', - success: 'Succes', + "De nieuwe opslag zal volledig functioneel zijn en u kunt er " + + "een minimum aantal munten opslaan zodat het geloofwaardig lijkt.", + create_fake_storage: "Nep versleutelde opslag aanmaken", + go_back: "Ga terug", + create_password: "Wachtwoord aanmaken", + create_password_explanation: + "Wachtwoord voor nep-opslag hoort niet overeen te komen met wachtwoord voor uw hoofdopslag", + password_should_not_match: + "Wachtwoord voor nep-opslag hoort niet overeen te komen met wachtwoord voor uw hoofdopslag", + retype_password: "Herhaal wachtwoord", + passwords_do_not_match: + "Wachtwoorden komen niet overeen, probeer het opnieuw", + success: "Succes" }, lnd: { - title: 'fondsen beheren', - choose_source_wallet: 'Kies een bron portemonnee', - refill_lnd_balance: 'Vul Lightning-portemonneesaldo bij', - refill: 'Bijvullen', - withdraw: 'Opvragen', - expired: 'Verlopen', - placeholder: 'Invoice', - sameWalletAsInvoiceError: 'U kunt geen factuur betalen met dezelfde portemonnee die is gebruikt om de factuur te maken.', + title: "fondsen beheren", + choose_source_wallet: "Kies een bron portemonnee", + refill_lnd_balance: "Vul Lightning-portemonneesaldo bij", + refill: "Bijvullen", + withdraw: "Opvragen", + expired: "Verlopen", + placeholder: "Invoice", + sameWalletAsInvoiceError: + "U kunt geen factuur betalen met dezelfde portemonnee die is gebruikt om de factuur te maken." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/pt_BR.js b/loc/pt_BR.js index 0c9a356734c..949772d16f1 100644 --- a/loc/pt_BR.js +++ b/loc/pt_BR.js @@ -1,250 +1,262 @@ module.exports = { _: { - storage_is_encrypted: 'Os arquivos estão criptografados, uma senha é necessária', - enter_password: 'Inserir senha', - bad_password: 'Senha errada, tente outra vez', - never: 'nunca', - continue: 'Continue', - ok: 'OK', + storage_is_encrypted: + "Os arquivos estão criptografados, uma senha é necessária", + enter_password: "Inserir senha", + bad_password: "Senha errada, tente outra vez", + never: "nunca", + continue: "Continue", + ok: "OK" }, wallets: { - options: 'opções', - select_wallet: 'Escolher carteira', - createBitcoinWallet: 'Antes de criar a carteira Lightning é preciso criar uma carteira Bitcoin, tudo bem?', + options: "opções", + select_wallet: "Escolher carteira", + createBitcoinWallet: + "Antes de criar a carteira Lightning é preciso criar uma carteira Bitcoin, tudo bem?", list: { - tabBarLabel: 'Carteiras', - app_name: 'Veles Wallet', - title: 'carteiras', - header: 'Uma carteira representa um par composto de uma chave privada secreta e um endereço de depósito que você pode compartilhar.', - add: 'adicionar wallet', - create_a_wallet: 'Criar uma carteira', - create_a_wallet1: 'é grátis e você pode criar', - create_a_wallet2: 'quantas você quiser', - latest_transaction: 'última transação', - empty_txs1: 'Suas transações aparecerão aqui,', - empty_txs2: 'nenhuma no momento', + tabBarLabel: "Carteiras", + app_name: "Veles Wallet", + title: "carteiras", + header: + "Uma carteira representa um par composto de uma chave privada secreta e um endereço de depósito que você pode compartilhar.", + add: "adicionar wallet", + create_a_wallet: "Criar uma carteira", + create_a_wallet1: "é grátis e você pode criar", + create_a_wallet2: "quantas você quiser", + latest_transaction: "última transação", + empty_txs1: "Suas transações aparecerão aqui,", + empty_txs2: "nenhuma no momento", empty_txs1_lightning: - 'A carteira Lightning faz transações super rápidas (coisa de segundos) e tem taxas ridiculamente baratas,' + - ' ideal para transações diárias e de baixo valor.', - empty_txs2_lightning: '\nPara começar a usar clique em "administrar fundos" e recarregue o seu saldo.', - tap_here_to_buy: 'Toque aqui para comprar Bitcoin', + "A carteira Lightning faz transações super rápidas (coisa de segundos) e tem taxas ridiculamente baratas," + + " ideal para transações diárias e de baixo valor.", + empty_txs2_lightning: + '\nPara começar a usar clique em "administrar fundos" e recarregue o seu saldo.', + tap_here_to_buy: "Toque aqui para comprar Bitcoin" }, reorder: { - title: 'Reordenar carteiras', + title: "Reordenar carteiras" }, add: { - title: 'criando carteira', + title: "criando carteira", description: - 'Você pode ler o backup de uma carteira (em WIF - Wallet Import Format) ou criar uma nova. O padrão é criar uma carteira SegWit.', - scan: 'Ler backup', - create: 'Criar', - label_new_segwit: 'Nova carteira SegWit', - label_new_lightning: 'Nova carteira Lightning', - wallet_name: 'nome', - wallet_type: 'tipo', - or: 'ou', - import_wallet: 'Importar carteira', - imported: 'Importado', - coming_soon: 'Em breve', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Você pode ler o backup de uma carteira (em WIF - Wallet Import Format) ou criar uma nova. O padrão é criar uma carteira SegWit.", + scan: "Ler backup", + create: "Criar", + label_new_segwit: "Nova carteira SegWit", + label_new_lightning: "Nova carteira Lightning", + wallet_name: "nome", + wallet_type: "tipo", + or: "ou", + import_wallet: "Importar carteira", + imported: "Importado", + coming_soon: "Em breve", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Carteira', - address: 'Endereço', - type: 'Tipo', - destination: 'destino', - description: 'descrição', - label: 'Nome', - are_you_sure: 'Tem certeza?', - yes_delete: 'Sim, apagar', - no_cancel: 'Não, cancelar', - delete_this_wallet: 'Apagar esta carteira', - export_backup: 'Exportar / backup', - buy_bitcoin: 'Comprar Bitcoin', - show_xpub: 'Ver XPUB', - delete: 'Apagar', - save: 'Salvar', + title: "Carteira", + address: "Endereço", + type: "Tipo", + destination: "destino", + description: "descrição", + label: "Nome", + are_you_sure: "Tem certeza?", + yes_delete: "Sim, apagar", + no_cancel: "Não, cancelar", + delete_this_wallet: "Apagar esta carteira", + export_backup: "Exportar / backup", + buy_bitcoin: "Comprar Bitcoin", + show_xpub: "Ver XPUB", + delete: "Apagar", + save: "Salvar" }, export: { - title: 'Exportar carteira', + title: "Exportar carteira" }, xpub: { - title: 'XPUB', - copiedToClipboard: 'Copiado para a área de transferência', + title: "XPUB", + copiedToClipboard: "Copiado para a área de transferência" }, import: { - title: 'importar', + title: "importar", explanation: - 'Escreva aqui sua frase mnemônica, chave privada, WIF, ou o que você tiver. Faremos nosso melhor para adivinhar o formato e importat sua carteira', - imported: 'Importada', - error: 'Erro. Por favor, confira se o formato que você passou é válido.', - success: 'Sucesso', - do_import: 'Importar', - scan_qr: 'ou ler um código QR?', + "Escreva aqui sua frase mnemônica, chave privada, WIF, ou o que você tiver. Faremos nosso melhor para adivinhar o formato e importat sua carteira", + imported: "Importada", + error: "Erro. Por favor, confira se o formato que você passou é válido.", + success: "Sucesso", + do_import: "Importar", + scan_qr: "ou ler um código QR?" }, scanQrWif: { - go_back: 'Voltar', - cancel: 'Cancelar', - decoding: 'Decodificar', - input_password: 'Inserir senha', - password_explain: 'Isto é um chave privada criptografada BIP38', - bad_password: 'Senha errada', - wallet_already_exists: 'Esta carteira já existe', - bad_wif: 'WIF errado', - imported_wif: 'WIF importado ', - with_address: ' com endereço ', - imported_segwit: 'Carteira SegWit importada', - imported_legacy: 'Carteira antiga importada', - imported_watchonly: 'Carteira somente-leitura importada', - }, + go_back: "Voltar", + cancel: "Cancelar", + decoding: "Decodificar", + input_password: "Inserir senha", + password_explain: "Isto é um chave privada criptografada BIP38", + bad_password: "Senha errada", + wallet_already_exists: "Esta carteira já existe", + bad_wif: "WIF errado", + imported_wif: "WIF importado ", + with_address: " com endereço ", + imported_segwit: "Carteira SegWit importada", + imported_legacy: "Carteira antiga importada", + imported_watchonly: "Carteira somente-leitura importada" + } }, transactions: { list: { - tabBarLabel: 'Transações', - title: 'Transações', - description: 'Uma lista de transações feitas ou recebidas nas suas carteiras', - conf: 'conf', + tabBarLabel: "Transações", + title: "Transações", + description: + "Uma lista de transações feitas ou recebidas nas suas carteiras", + conf: "conf" }, details: { - title: 'Transação', - from: 'De', - to: 'Para', - copy: 'Copiar', - transaction_details: 'Detalhes', - show_in_block_explorer: 'Mostrar num navegador', - }, + title: "Transação", + from: "De", + to: "Para", + copy: "Copiar", + transaction_details: "Detalhes", + show_in_block_explorer: "Mostrar num navegador" + } }, send: { - header: 'Enviar', + header: "Enviar", confirm: { - header: 'Confirmar', - sendNow: 'Enviar agora', + header: "Confirmar", + sendNow: "Enviar agora" }, success: { - done: 'Enviado', + done: "Enviado" }, details: { - title: 'Criar Transacção', - amount_field_is_not_valid: 'Campo de quantia não é válido', - fee_field_is_not_valid: 'Campo de taxa não é válido', - address_field_is_not_valid: 'Campo de endereço não é válido', - receiver_placeholder: 'endereço de envio aqui', - amount_placeholder: 'quantia a enviar (em VLS)', - fee_placeholder: 'mais a taxa de transacção (em VLS)', - create_tx_error: 'Erro na criação da transação, por favor confira se o endereço é válido.', - note_placeholder: 'Nota pessoal', - cancel: 'Cancelar', - scan: 'Scanear', - create: 'Criar', - address: 'Endereço', - total_exceeds_balance: 'Valor total excede o saldo disponível', - send: 'Send', - remaining_balance: 'Saldo restante', + title: "Criar Transacção", + amount_field_is_not_valid: "Campo de quantia não é válido", + fee_field_is_not_valid: "Campo de taxa não é válido", + address_field_is_not_valid: "Campo de endereço não é válido", + receiver_placeholder: "endereço de envio aqui", + amount_placeholder: "quantia a enviar (em VLS)", + fee_placeholder: "mais a taxa de transacção (em VLS)", + create_tx_error: + "Erro na criação da transação, por favor confira se o endereço é válido.", + note_placeholder: "Nota pessoal", + cancel: "Cancelar", + scan: "Scanear", + create: "Criar", + address: "Endereço", + total_exceeds_balance: "Valor total excede o saldo disponível", + send: "Send", + remaining_balance: "Saldo restante" }, create: { - title: 'Criar Transacção', - details: 'Detalhes', - error: 'Erro ao criar transação. Endereço ou valor inválidos?', - go_back: 'Voltar', - this_is_hex: 'Este é o hex da transação, assinado e pronto para ser divulgado para o mundo. Continuar?', - to: 'Para', - amount: 'Valor', - fee: 'Taxa', - tx_size: 'Tamanho', - satoshi_per_byte: 'satoshis por byte', - memo: 'Nota', - broadcast: 'Divulgar', - not_enough_fee: 'Taxa muito baixa. Aumente a taxa', - }, + title: "Criar Transacção", + details: "Detalhes", + error: "Erro ao criar transação. Endereço ou valor inválidos?", + go_back: "Voltar", + this_is_hex: + "Este é o hex da transação, assinado e pronto para ser divulgado para o mundo. Continuar?", + to: "Para", + amount: "Valor", + fee: "Taxa", + tx_size: "Tamanho", + satoshi_per_byte: "satoshis por byte", + memo: "Nota", + broadcast: "Divulgar", + not_enough_fee: "Taxa muito baixa. Aumente a taxa" + } }, receive: { - header: 'Receber', + header: "Receber", details: { - title: 'Envie este endereço para o pagador', - share: 'Compartilhar', - copiedToClipboard: 'Copiado para a área de trabalho', - label: 'Descrição', - create: 'Create', - setAmount: 'Valor a receber', + title: "Envie este endereço para o pagador", + share: "Compartilhar", + copiedToClipboard: "Copiado para a área de trabalho", + label: "Descrição", + create: "Create", + setAmount: "Valor a receber" }, - scan_lnurl: 'Receber lendo QR', + scan_lnurl: "Receber lendo QR" }, buyBitcoin: { - header: 'Comprar Bitcoin', - tap_your_address: 'Toque seu endereço para copiá-lo para a área de transferência:', - copied: 'Copiado!', + header: "Comprar Bitcoin", + tap_your_address: + "Toque seu endereço para copiá-lo para a área de transferência:", + copied: "Copiado!" }, settings: { - tabBarLabel: 'preferências', - header: 'definições', - plausible_deniability: 'Negação plausível...', - storage_not_encrypted: 'Arquivos: não criptografados', - storage_encrypted: 'Arquivos: criptografados', - password: 'Senha', - password_explain: 'Definir a senha para descriptografar os arquivos', - retype_password: 'Inserir senha novamente', - passwords_do_not_match: 'Senhas não coincidem', - encrypt_storage: 'Criptografar', - lightning_settings: 'Preferências Lightning', + tabBarLabel: "preferências", + header: "definições", + plausible_deniability: "Negação plausível...", + storage_not_encrypted: "Arquivos: não criptografados", + storage_encrypted: "Arquivos: criptografados", + password: "Senha", + password_explain: "Definir a senha para descriptografar os arquivos", + retype_password: "Inserir senha novamente", + passwords_do_not_match: "Senhas não coincidem", + encrypt_storage: "Criptografar", + lightning_settings: "Preferências Lightning", lightning_settings_explain: - 'Para se conectar ao seu próprio ponto LND, você precisa instalar a aplicação LndHub' + - ' e copiar sua URL para cá. Deixe em branco para usar a LndHub padrão fornecida pela Veles Wallet (lndhub.io).' + - ' Carteiras criadas após mudanças nestas preferências ficarão ligadas à instância LndHub que estiver especificada.', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Salvar', - about: 'Sobre', - language: 'Idioma', - currency: 'Moeda', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Para se conectar ao seu próprio ponto LND, você precisa instalar a aplicação LndHub" + + " e copiar sua URL para cá. Deixe em branco para usar a LndHub padrão fornecida pela Veles Wallet (lndhub.io)." + + " Carteiras criadas após mudanças nestas preferências ficarão ligadas à instância LndHub que estiver especificada.", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Salvar", + about: "Sobre", + language: "Idioma", + currency: "Moeda", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Negação plausível', + title: "Negação plausível", help: - 'Em algumas circunstâncias, você pode ser forçado a revelar uma ' + - 'senha. Para manter seus bitcoins seguros, A Veles Wallet pode criar ' + - 'uma senha alternativa. Sob pressão, você pode revelar essa senha ao ' + - 'invés da senha principal. Quando inserida na Veles Wallet, esta abrirá ' + - 'uma interface falsa, que parecerá legítima a um terceiro, enquanto ' + - 'suas carteiras originais continuarão à salvo em segredo.', + "Em algumas circunstâncias, você pode ser forçado a revelar uma " + + "senha. Para manter seus bitcoins seguros, A Veles Wallet pode criar " + + "uma senha alternativa. Sob pressão, você pode revelar essa senha ao " + + "invés da senha principal. Quando inserida na Veles Wallet, esta abrirá " + + "uma interface falsa, que parecerá legítima a um terceiro, enquanto " + + "suas carteiras originais continuarão à salvo em segredo.", help2: - 'Essa nova interface é completamente funcional e você pode inclusive ' + 'manter nele um valor minímo para que pareça mais real.', - create_fake_storage: 'Criar armazenamento criptografada falsa', - go_back: 'Voltar', - create_password: 'Criar senha', - create_password_explanation: 'A senha para a interface falsa não deve coincidir com a principal', - password_should_not_match: 'A senha para a interface falsa não deve coincidir com a principal', - retype_password: 'Inserir senha novamente', - passwords_do_not_match: 'Senhas não coincidem, tente novamente', - success: 'Sucesso', + "Essa nova interface é completamente funcional e você pode inclusive " + + "manter nele um valor minímo para que pareça mais real.", + create_fake_storage: "Criar armazenamento criptografada falsa", + go_back: "Voltar", + create_password: "Criar senha", + create_password_explanation: + "A senha para a interface falsa não deve coincidir com a principal", + password_should_not_match: + "A senha para a interface falsa não deve coincidir com a principal", + retype_password: "Inserir senha novamente", + passwords_do_not_match: "Senhas não coincidem, tente novamente", + success: "Sucesso" }, lnd: { - title: 'administrar fundos', - choose_source_wallet: 'Escolha a carteira de origem', - refill_lnd_balance: 'Recarregar a carteira Lightning', - refill: 'Recarregar', - placeholder: 'Invoice', - withdraw: 'Sacar', - expired: 'Vencido', - sameWalletAsInvoiceError: 'Você não pode pagar uma fatura com a mesma carteira que a criou.', + title: "administrar fundos", + choose_source_wallet: "Escolha a carteira de origem", + refill_lnd_balance: "Recarregar a carteira Lightning", + refill: "Recarregar", + placeholder: "Invoice", + withdraw: "Sacar", + expired: "Vencido", + sameWalletAsInvoiceError: + "Você não pode pagar uma fatura com a mesma carteira que a criou." }, pleasebackup: { - title: 'Sua carteira foi criada...', + title: "Sua carteira foi criada...", text: - 'Por favor anote num pedaço de papel essa seqüência de palavras, elas serão o seu backup e você as pode usar para' + - ' recuperar a sua carteira em outros dispositivos.', - ok: 'Certo, já anotei!', + "Por favor anote num pedaço de papel essa seqüência de palavras, elas serão o seu backup e você as pode usar para" + + " recuperar a sua carteira em outros dispositivos.", + ok: "Certo, já anotei!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/pt_PT.js b/loc/pt_PT.js index cdb3621fbcc..c33835f2765 100644 --- a/loc/pt_PT.js +++ b/loc/pt_PT.js @@ -1,248 +1,261 @@ module.exports = { _: { - storage_is_encrypted: 'O armazenamento está encriptado. Uma password é necessária para desencriptar', - enter_password: 'Inserir password', - bad_password: 'pasword errada, tente novamente', - never: 'nunca', - continue: 'Continuar', - ok: 'OK', + storage_is_encrypted: + "O armazenamento está encriptado. Uma password é necessária para desencriptar", + enter_password: "Inserir password", + bad_password: "pasword errada, tente novamente", + never: "nunca", + continue: "Continuar", + ok: "OK" }, wallets: { - options: 'opções', - select_wallet: 'Seleccione uma Wallet', - createBitcoinWallet: 'Para poder usar uma wallet Lightning, é necessária uma wallet Bitcoin para a financiar. Deseja continuar?', + options: "opções", + select_wallet: "Seleccione uma Wallet", + createBitcoinWallet: + "Para poder usar uma wallet Lightning, é necessária uma wallet Bitcoin para a financiar. Deseja continuar?", list: { - app_name: 'Veles Wallet', - title: 'wallets', - header: 'Uma wallet representa um par entre um segredo (chave privada) e um endereço' + 'que pode partilhar para receber Bitcoin.', - add: 'adicionar wallet', - create_a_wallet: 'Adicionar uma wallet', - create_a_wallet1: 'É gratuito e pode', - create_a_wallet2: 'adicionar quantas quiser', - latest_transaction: 'últimas transacções', - empty_txs1: 'As suas transacções aparecerão aqui,', - empty_txs2: 'nenhuma de momento', + app_name: "Veles Wallet", + title: "wallets", + header: + "Uma wallet representa um par entre um segredo (chave privada) e um endereço" + + "que pode partilhar para receber Bitcoin.", + add: "adicionar wallet", + create_a_wallet: "Adicionar uma wallet", + create_a_wallet1: "É gratuito e pode", + create_a_wallet2: "adicionar quantas quiser", + latest_transaction: "últimas transacções", + empty_txs1: "As suas transacções aparecerão aqui,", + empty_txs2: "nenhuma de momento", empty_txs1_lightning: - 'A wallet Lightning deve ser usada para as suas transações diárias. As taxas são muito baixas e a velocidade muito elevada', - empty_txs2_lightning: '\nPara começar a usar toque em "gerir fundos" e recarregue o seu saldo.', - tap_here_to_buy: 'Toque aqui para comprar Bitcoin', + "A wallet Lightning deve ser usada para as suas transações diárias. As taxas são muito baixas e a velocidade muito elevada", + empty_txs2_lightning: + '\nPara começar a usar toque em "gerir fundos" e recarregue o seu saldo.', + tap_here_to_buy: "Toque aqui para comprar Bitcoin" }, reorder: { - title: 'Reordenar Wallets', + title: "Reordenar Wallets" }, add: { - title: 'adicionar wallet', + title: "adicionar wallet", description: - 'Pode fazer um scan de um backup de uma wallet em papel (em WIF - Wallet Import Format), ou criar uma nova wallet. Segwit suportado por defeito.', - scan: 'Scan', - create: 'Adicionar', - label_new_segwit: 'Novo SegWit', - label_new_lightning: 'Novo Lightning', - wallet_name: 'nome', - wallet_type: 'tipo', - or: 'ou', - import_wallet: 'Importar wallet', - imported: 'Importada', - coming_soon: 'Brevemente', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Pode fazer um scan de um backup de uma wallet em papel (em WIF - Wallet Import Format), ou criar uma nova wallet. Segwit suportado por defeito.", + scan: "Scan", + create: "Adicionar", + label_new_segwit: "Novo SegWit", + label_new_lightning: "Novo Lightning", + wallet_name: "nome", + wallet_type: "tipo", + or: "ou", + import_wallet: "Importar wallet", + imported: "Importada", + coming_soon: "Brevemente", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'wallet', - address: 'Endereço', - type: 'Tipo', - delete: 'Eliminar', - save: 'Guardar', - label: 'Nome', - destination: 'destino', - description: 'descrição', - are_you_sure: 'Tem a certeza?', - yes_delete: 'Sim, eliminar', - no_cancel: 'Não, cancelar', - delete_this_wallet: 'Apagar esta wallet', - export_backup: 'Exportar / backup', - buy_bitcoin: 'Comprar Bitcoin', - show_xpub: 'Mostar XPUB da wallet', + title: "wallet", + address: "Endereço", + type: "Tipo", + delete: "Eliminar", + save: "Guardar", + label: "Nome", + destination: "destino", + description: "descrição", + are_you_sure: "Tem a certeza?", + yes_delete: "Sim, eliminar", + no_cancel: "Não, cancelar", + delete_this_wallet: "Apagar esta wallet", + export_backup: "Exportar / backup", + buy_bitcoin: "Comprar Bitcoin", + show_xpub: "Mostar XPUB da wallet" }, export: { - title: 'Exportar Wallet', + title: "Exportar Wallet" }, xpub: { - title: 'XPUB da wallet', - copiedToClipboard: 'copiado para o clipboard', + title: "XPUB da wallet", + copiedToClipboard: "copiado para o clipboard" }, import: { - title: 'importar', + title: "importar", explanation: - 'Escreva a sua frase mnemónica, chave privada, WIF, ou qualquer informação que disponha. Vamos tentar interpretar o formato e importar a sua wallet', - imported: 'Importada', - error: 'Falhou. É um dado válido?', - success: 'Sucesso', - do_import: 'Importar', - scan_qr: 'ou scan o QR code?', + "Escreva a sua frase mnemónica, chave privada, WIF, ou qualquer informação que disponha. Vamos tentar interpretar o formato e importar a sua wallet", + imported: "Importada", + error: "Falhou. É um dado válido?", + success: "Sucesso", + do_import: "Importar", + scan_qr: "ou scan o QR code?" }, scanQrWif: { - go_back: 'Voltar', - cancel: 'Cancelar', - decoding: 'Descodificar', - input_password: 'Inserir password', - password_explain: 'Isto é uma chave privada encriptada BIP38', - bad_password: 'Password errada', - wallet_already_exists: 'Esta wallet já existe', - bad_wif: 'WIF errado', - imported_wif: 'WIF transferido ', - with_address: ' com endereço ', - imported_segwit: 'SegWit transferido', - imported_legacy: 'Legacy transferido', - imported_watchonly: 'Watch-only importada', - }, + go_back: "Voltar", + cancel: "Cancelar", + decoding: "Descodificar", + input_password: "Inserir password", + password_explain: "Isto é uma chave privada encriptada BIP38", + bad_password: "Password errada", + wallet_already_exists: "Esta wallet já existe", + bad_wif: "WIF errado", + imported_wif: "WIF transferido ", + with_address: " com endereço ", + imported_segwit: "SegWit transferido", + imported_legacy: "Legacy transferido", + imported_watchonly: "Watch-only importada" + } }, transactions: { list: { - tabBarLabel: 'Transacções', - title: 'transacções', - description: 'Uma lista de transacções feitas ou recebidas nas suas wallets', - conf: 'conf', + tabBarLabel: "Transacções", + title: "transacções", + description: + "Uma lista de transacções feitas ou recebidas nas suas wallets", + conf: "conf" }, details: { - title: 'detalhes', - from: 'De', - to: 'Para', - copy: 'Copiar', - transaction_details: 'Detalhes da transacção', - show_in_block_explorer: 'Mostrar no block explorer', - }, + title: "detalhes", + from: "De", + to: "Para", + copy: "Copiar", + transaction_details: "Detalhes da transacção", + show_in_block_explorer: "Mostrar no block explorer" + } }, send: { - header: 'Enviar', + header: "Enviar", confirm: { - header: 'Confirmar', - sendNow: 'Enviar agora', + header: "Confirmar", + sendNow: "Enviar agora" }, success: { - done: 'Done', + done: "Done" }, details: { - title: 'Criar Transacção', - amount_field_is_not_valid: 'Campo de quantia não é válido', - fee_field_is_not_valid: 'Campo de taxa não é válido', - address_field_is_not_valid: 'Campo de endereço não é válido', - receiver_placeholder: 'endereço de envio aqui', - amount_placeholder: 'quantia a enviar (em VLS)', - fee_placeholder: 'mais a taxa de transacção (em VLS)', - create_tx_error: 'Houve um erro na criação da transacção. Por favor verifique que o endereço é válido.', - note_placeholder: 'Nota pessoal', - total_exceeds_balance: 'O valor total excede o saldo disponível.', - cancel: 'Cancelar', - scan: 'Scan', - create: 'Criar', - address: 'Endereço', - send: 'Enviar', - remaining_balance: 'Saldo restante', + title: "Criar Transacção", + amount_field_is_not_valid: "Campo de quantia não é válido", + fee_field_is_not_valid: "Campo de taxa não é válido", + address_field_is_not_valid: "Campo de endereço não é válido", + receiver_placeholder: "endereço de envio aqui", + amount_placeholder: "quantia a enviar (em VLS)", + fee_placeholder: "mais a taxa de transacção (em VLS)", + create_tx_error: + "Houve um erro na criação da transacção. Por favor verifique que o endereço é válido.", + note_placeholder: "Nota pessoal", + total_exceeds_balance: "O valor total excede o saldo disponível.", + cancel: "Cancelar", + scan: "Scan", + create: "Criar", + address: "Endereço", + send: "Enviar", + remaining_balance: "Saldo restante" }, create: { - title: 'Criar Transacção', - details: 'Detalhes', - error: 'Erro ao criar transacção. Endereço inválido ou quantia?', - go_back: 'Voltar', - this_is_hex: 'Este é o hex da transacção, assinado e pronto para ser difundido para a network. Continuar?', - to: 'Para', - amount: 'Quantia', - fee: 'Taxa', - tx_size: 'Tamanho TX', - satoshi_per_byte: 'satoshiPerByte', - memo: 'Nota pessoal', - broadcast: 'Difundir', - not_enough_fee: 'Taxa demasiado baixo. Aumente a taxa.', - }, + title: "Criar Transacção", + details: "Detalhes", + error: "Erro ao criar transacção. Endereço inválido ou quantia?", + go_back: "Voltar", + this_is_hex: + "Este é o hex da transacção, assinado e pronto para ser difundido para a network. Continuar?", + to: "Para", + amount: "Quantia", + fee: "Taxa", + tx_size: "Tamanho TX", + satoshi_per_byte: "satoshiPerByte", + memo: "Nota pessoal", + broadcast: "Difundir", + not_enough_fee: "Taxa demasiado baixo. Aumente a taxa." + } }, buyBitcoin: { - header: 'Comprar Bitcoin', - tap_your_address: 'Toque no seu endereço para o copiar para o clipboard:', - copied: 'Copied to Clipboard!', + header: "Comprar Bitcoin", + tap_your_address: "Toque no seu endereço para o copiar para o clipboard:", + copied: "Copied to Clipboard!" }, receive: { - header: 'receber', + header: "receber", details: { - title: 'Partilhar este endereço com o pagador', - share: 'partilhar', - copiedToClipboard: 'copiado para clipboard', - label: 'Descrição', - create: 'Criar', - setAmount: 'Quantia a receber', + title: "Partilhar este endereço com o pagador", + share: "partilhar", + copiedToClipboard: "copiado para clipboard", + label: "Descrição", + create: "Criar", + setAmount: "Quantia a receber" }, - scan_lnurl: 'Receber lendo QR', + scan_lnurl: "Receber lendo QR" }, settings: { - tabBarLabel: 'Definições', - header: 'definições', - plausible_deniability: 'Negação plausível...', - storage_not_encrypted: 'Armazenamento: não encriptado', - storage_encrypted: 'Armazenamento: encriptado', - password: 'Password', - password_explain: 'Definir a password para desencriptar o armazenamento', - retype_password: 'Inserir password novamente', - passwords_do_not_match: 'Passwords não coincidem', - encrypt_storage: 'Encriptar', - lightning_settings: 'Definições do Lightning', + tabBarLabel: "Definições", + header: "definições", + plausible_deniability: "Negação plausível...", + storage_not_encrypted: "Armazenamento: não encriptado", + storage_encrypted: "Armazenamento: encriptado", + password: "Password", + password_explain: "Definir a password para desencriptar o armazenamento", + retype_password: "Inserir password novamente", + passwords_do_not_match: "Passwords não coincidem", + encrypt_storage: "Encriptar", + lightning_settings: "Definições do Lightning", lightning_settings_explain: - 'Para se ligar ao seu próprio node LND, por favor instale o LndHub ' + - 'e coloque o seu endereço aqui nas definições. ' + - 'Deixe em branco para usar o LNDHub da Veles Wallet (lndhub.io). ' + - 'Wallets criadas depois desta alteração ligar-se-ão ao LNDHub especificado.', - electrum_settings: 'Definições do Electrum', - electrum_settings_explain: 'Deixe em branco para usar o valor por omissão', - save: 'Guardar', - about: 'Sobre', - language: 'Idioma', - currency: 'Moeda', - advanced_options: 'Opções Avançadas', - enable_advanced_mode: 'Ligar modo avançado', + "Para se ligar ao seu próprio node LND, por favor instale o LndHub " + + "e coloque o seu endereço aqui nas definições. " + + "Deixe em branco para usar o LNDHub da Veles Wallet (lndhub.io). " + + "Wallets criadas depois desta alteração ligar-se-ão ao LNDHub especificado.", + electrum_settings: "Definições do Electrum", + electrum_settings_explain: "Deixe em branco para usar o valor por omissão", + save: "Guardar", + about: "Sobre", + language: "Idioma", + currency: "Moeda", + advanced_options: "Opções Avançadas", + enable_advanced_mode: "Ligar modo avançado" }, plausibledeniability: { - title: 'Negação plausível', + title: "Negação plausível", help: - 'Em algumas circunstâncias, pode ser forçado a relevar uma ' + - 'password. Para manter as suas moedas seguras, A Veles Wallet pode criar outro ' + - 'armazenamento encriptado, com uma password diferente. Sobre pressão, ' + - 'pode revelar esta password a um terceiro. Se inserida na ' + + "Em algumas circunstâncias, pode ser forçado a relevar uma " + + "password. Para manter as suas moedas seguras, A Veles Wallet pode criar outro " + + "armazenamento encriptado, com uma password diferente. Sobre pressão, " + + "pode revelar esta password a um terceiro. Se inserida na " + 'Veles Wallet, esta vai abrir um armazenamento "falso". Que vai parecer ' + - 'legítimo a um terceiro, mas que secretamente vai manter o seu armazenamento principal ' + - 'com as moedas em segurança.', - help2: 'Este novo armazenamento é completamente funcional, e pode guardar ' + 'um valor minímo para parecer mais real.', - create_fake_storage: 'Criar armazenamento encriptado FALSO', - go_back: 'Voltar', - create_password: 'Criar password', - create_password_explanation: 'Password para armazenamento FALSO não deve coincidir com a password principal', - password_should_not_match: 'Password para armazenamento FALSO não deve coincidir com a password principal', - retype_password: 'Inserir password novamente', - passwords_do_not_match: 'Passwords não coincidem, tente novamente', - success: 'Sucesso', + "legítimo a um terceiro, mas que secretamente vai manter o seu armazenamento principal " + + "com as moedas em segurança.", + help2: + "Este novo armazenamento é completamente funcional, e pode guardar " + + "um valor minímo para parecer mais real.", + create_fake_storage: "Criar armazenamento encriptado FALSO", + go_back: "Voltar", + create_password: "Criar password", + create_password_explanation: + "Password para armazenamento FALSO não deve coincidir com a password principal", + password_should_not_match: + "Password para armazenamento FALSO não deve coincidir com a password principal", + retype_password: "Inserir password novamente", + passwords_do_not_match: "Passwords não coincidem, tente novamente", + success: "Sucesso" }, lnd: { - title: 'gerir saldo', - choose_source_wallet: 'Escolha a wallet', - refill_lnd_balance: 'Carregar o saldo da Lightning wallet', - refill: 'Carregar', - placeholder: 'Factura', - withdraw: 'Transferir', - expired: 'Expirado', - sameWalletAsInvoiceError: 'Não pode pagar uma factura com a mesma wallet usada para a criar.', + title: "gerir saldo", + choose_source_wallet: "Escolha a wallet", + refill_lnd_balance: "Carregar o saldo da Lightning wallet", + refill: "Carregar", + placeholder: "Factura", + withdraw: "Transferir", + expired: "Expirado", + sameWalletAsInvoiceError: + "Não pode pagar uma factura com a mesma wallet usada para a criar." }, pleasebackup: { - title: 'A sua wallet foi criada...', + title: "A sua wallet foi criada...", text: - 'Por favor escreva esta frase mnemónica numa folha de papel. É o seu backup e pode usá-lo para restaurar a sua wallet noutro device.', - ok: 'OK, eu escrevi-a num papel!', + "Por favor escreva esta frase mnemónica numa folha de papel. É o seu backup e pode usá-lo para restaurar a sua wallet noutro device.", + ok: "OK, eu escrevi-a num papel!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'Esta factura não foi paga e expirou', - has_been_paid: 'Esta factura foi paga', - please_pay: 'Por favor pague', - sats: 'sats', - for: 'Para:', - additional_info: 'Informação adicional', - open_direct_channel: 'Abrir canal directo com este node:', - }, + wasnt_paid_and_expired: "Esta factura não foi paga e expirou", + has_been_paid: "Esta factura foi paga", + please_pay: "Por favor pague", + sats: "sats", + for: "Para:", + additional_info: "Informação adicional", + open_direct_channel: "Abrir canal directo com este node:" + } }; diff --git a/loc/ru.js b/loc/ru.js index bd2e1939644..bd7640ffdc7 100644 --- a/loc/ru.js +++ b/loc/ru.js @@ -1,248 +1,259 @@ module.exports = { _: { - storage_is_encrypted: 'Твоё хранилище зашифровано. Введи пароль для расшифровки', - enter_password: 'Введи пароль', - bad_password: 'Неверный пароль, попробуй еще раз', - never: 'Никогда', - continue: 'Продолжить', - ok: 'OK', + storage_is_encrypted: + "Твоё хранилище зашифровано. Введи пароль для расшифровки", + enter_password: "Введи пароль", + bad_password: "Неверный пароль, попробуй еще раз", + never: "Никогда", + continue: "Продолжить", + ok: "OK" }, wallets: { - options: 'Настройки', - select_wallet: 'Выбрать кошелек', - createBitcoinWallet: 'Чтобы воспользоватья кошельком Lightning, нужно сначала пополнить его с помощью кошелька Bitcoin. Продолжить?', + options: "Настройки", + select_wallet: "Выбрать кошелек", + createBitcoinWallet: + "Чтобы воспользоватья кошельком Lightning, нужно сначала пополнить его с помощью кошелька Bitcoin. Продолжить?", list: { - app_name: 'Veles Wallet', - title: 'Кошельки', - header: 'Кошелек - это секретный (приватный) ключ и соответствующий ему адрес на который можно получать Bitcoin', - add: 'Добавить Кошелек', - create_a_wallet: 'Создать кошелек', - create_a_wallet1: 'Это бесплатно и ты можешь создать', - create_a_wallet2: 'неограниченное количество', - latest_transaction: 'Последняя транзакция', - empty_txs1: 'Список транзакций пока пуст', - empty_txs2: ' ', + app_name: "Veles Wallet", + title: "Кошельки", + header: + "Кошелек - это секретный (приватный) ключ и соответствующий ему адрес на который можно получать Bitcoin", + add: "Добавить Кошелек", + create_a_wallet: "Создать кошелек", + create_a_wallet1: "Это бесплатно и ты можешь создать", + create_a_wallet2: "неограниченное количество", + latest_transaction: "Последняя транзакция", + empty_txs1: "Список транзакций пока пуст", + empty_txs2: " ", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Купить Bitcoin', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Купить Bitcoin" }, reorder: { - title: 'Отсортировать кошельки', + title: "Отсортировать кошельки" }, add: { - title: 'Добавить кошелек', + title: "Добавить кошелек", description: - 'Ты можешь отсканировать QR код (в формате WIF - Wallet Import Format) или создать новый кошелек. Segwit поддерживается по умолчанию.', - scan: 'Отсканировать', - create: 'Создать', - label_new_segwit: 'Новый SegWit', - label_new_lightning: 'Новый Lightning', - wallet_name: 'Имя кошелька', - wallet_type: 'Тип кошелька', - or: 'или', - import_wallet: 'Импортировать кошелек', - imported: 'Кошелек импортирован', - coming_soon: 'Скоро будет', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Ты можешь отсканировать QR код (в формате WIF - Wallet Import Format) или создать новый кошелек. Segwit поддерживается по умолчанию.", + scan: "Отсканировать", + create: "Создать", + label_new_segwit: "Новый SegWit", + label_new_lightning: "Новый Lightning", + wallet_name: "Имя кошелька", + wallet_type: "Тип кошелька", + or: "или", + import_wallet: "Импортировать кошелек", + imported: "Кошелек импортирован", + coming_soon: "Скоро будет", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Информация о кошельке', - address: 'Адрес', - type: 'Тип', - label: 'Метка', - delete: 'Удалить', - save: 'Сохранить', - are_you_sure: 'Точно удалить?', - yes_delete: 'Да, удалить', - destination: 'Назначение', - description: 'Описание', - no_cancel: 'Нет, отмена', - delete_this_wallet: 'Удалить этот кошелек', - export_backup: 'Экспорт / резервная копия', - buy_bitcoin: 'Купить Bitcoin', - show_xpub: 'Показать XPUB', + title: "Информация о кошельке", + address: "Адрес", + type: "Тип", + label: "Метка", + delete: "Удалить", + save: "Сохранить", + are_you_sure: "Точно удалить?", + yes_delete: "Да, удалить", + destination: "Назначение", + description: "Описание", + no_cancel: "Нет, отмена", + delete_this_wallet: "Удалить этот кошелек", + export_backup: "Экспорт / резервная копия", + buy_bitcoin: "Купить Bitcoin", + show_xpub: "Показать XPUB" }, export: { - title: 'Экспорт Кошелька', + title: "Экспорт Кошелька" }, xpub: { - title: 'XPUB кошелька', - copiedToClipboard: 'Скопировано', + title: "XPUB кошелька", + copiedToClipboard: "Скопировано" }, import: { - title: 'Импорт', - explanation: 'Напиши тут свою мнемоническую фразу, приватный ключ, WIF - что угодно! Veles Wallet постарается угадать верный формат', - imported: 'Импорт завершен', - error: 'Не удалось импортировать', - success: 'Успех', - do_import: 'Импортировать', - scan_qr: 'или отсканировать QR код?', + title: "Импорт", + explanation: + "Напиши тут свою мнемоническую фразу, приватный ключ, WIF - что угодно! Veles Wallet постарается угадать верный формат", + imported: "Импорт завершен", + error: "Не удалось импортировать", + success: "Успех", + do_import: "Импортировать", + scan_qr: "или отсканировать QR код?" }, scanQrWif: { - go_back: 'Назад', - cancel: 'Отмена', - decoding: 'Расшивровываю', - input_password: 'Введи пароль', - password_explain: 'Приватный ключ зашифрован по стандарту BIP38', - bad_password: 'Неверный пароль', - wallet_already_exists: 'Такой кошелек уже существует', - bad_wif: 'Некорректный WIF', - imported_wif: 'Импортирован WIF ', - with_address: ' с адресом ', - imported_segwit: 'Импортированый SegWit', - imported_legacy: 'Импортированый Legacy', - imported_watchonly: 'Импортированый Watch-only', - }, + go_back: "Назад", + cancel: "Отмена", + decoding: "Расшивровываю", + input_password: "Введи пароль", + password_explain: "Приватный ключ зашифрован по стандарту BIP38", + bad_password: "Неверный пароль", + wallet_already_exists: "Такой кошелек уже существует", + bad_wif: "Некорректный WIF", + imported_wif: "Импортирован WIF ", + with_address: " с адресом ", + imported_segwit: "Импортированый SegWit", + imported_legacy: "Импортированый Legacy", + imported_watchonly: "Импортированый Watch-only" + } }, transactions: { list: { - tabBarLabel: 'Транзакции', - title: 'Мои транзакции', - description: 'Список входящих или исходящих транзакций ваших кошельков', - conf: 'подтв.', + tabBarLabel: "Транзакции", + title: "Мои транзакции", + description: "Список входящих или исходящих транзакций ваших кошельков", + conf: "подтв." }, details: { - title: 'Детали транзакци', - from: 'От', - to: 'Кому', - copy: 'копировать', - transaction_details: 'Детали транзакции', - show_in_block_explorer: 'Показать транзакцию в блокчейне', - }, + title: "Детали транзакци", + from: "От", + to: "Кому", + copy: "копировать", + transaction_details: "Детали транзакции", + show_in_block_explorer: "Показать транзакцию в блокчейне" + } }, send: { - header: 'Отправить', + header: "Отправить", confirm: { - header: 'Подтвердить', - sendNow: 'Отправить', + header: "Подтвердить", + sendNow: "Отправить" }, success: { - done: 'Готово', + done: "Готово" }, details: { - title: 'Создать Транзакцию', - amount_field_is_not_valid: 'Введенная сумма неверна', - fee_field_is_not_valid: 'Введенная комиссия неверна', - address_field_is_not_valid: 'Введенный адрес неверный', - receiver_placeholder: 'Адрес получателя', - amount_placeholder: 'сколько отправить (в VLS)', - fee_placeholder: 'плюс комиссия за перевод (в VLS)', - note_placeholder: 'примечание платежа', - create_tx_error: 'Ошибка при создании транзакции. Пожалуйста, проверь правильность адреса.', - cancel: 'Отмена', - scan: 'Отсканировать QR', - create: 'Создать', - send: 'Отправить', - address: 'Адрес', - total_exceeds_balance: 'Общая сумма превышает баланс.', - remaining_balance: 'Остаток баланса', + title: "Создать Транзакцию", + amount_field_is_not_valid: "Введенная сумма неверна", + fee_field_is_not_valid: "Введенная комиссия неверна", + address_field_is_not_valid: "Введенный адрес неверный", + receiver_placeholder: "Адрес получателя", + amount_placeholder: "сколько отправить (в VLS)", + fee_placeholder: "плюс комиссия за перевод (в VLS)", + note_placeholder: "примечание платежа", + create_tx_error: + "Ошибка при создании транзакции. Пожалуйста, проверь правильность адреса.", + cancel: "Отмена", + scan: "Отсканировать QR", + create: "Создать", + send: "Отправить", + address: "Адрес", + total_exceeds_balance: "Общая сумма превышает баланс.", + remaining_balance: "Остаток баланса" }, create: { - title: 'Создать Транзакцию', - details: 'Детали', - error: 'Ошибка при создании транзакции. Неправильный адрес назначения или недостаточно средств?', - go_back: 'Назад', - this_is_hex: 'Это данные транзакции. Транзакция подписана и готова быть транслирована в сеть. Продолжить?', - to: 'Куда', - amount: 'Сколько', - fee: 'Комиссия', - tx_size: 'Размер', - satoshi_per_byte: 'Сатоши на байт', - memo: 'Примечание', - broadcast: 'Отправить', - not_enough_fee: 'Слишком маленькая комиссия. Увеличь комиссию', - }, + title: "Создать Транзакцию", + details: "Детали", + error: + "Ошибка при создании транзакции. Неправильный адрес назначения или недостаточно средств?", + go_back: "Назад", + this_is_hex: + "Это данные транзакции. Транзакция подписана и готова быть транслирована в сеть. Продолжить?", + to: "Куда", + amount: "Сколько", + fee: "Комиссия", + tx_size: "Размер", + satoshi_per_byte: "Сатоши на байт", + memo: "Примечание", + broadcast: "Отправить", + not_enough_fee: "Слишком маленькая комиссия. Увеличь комиссию" + } }, buyBitcoin: { - header: 'Купить Bitcoin', - tap_your_address: 'Нажми на адрес, чтобы скопировать его:', - copied: 'Скопировано', + header: "Купить Bitcoin", + tap_your_address: "Нажми на адрес, чтобы скопировать его:", + copied: "Скопировано" }, receive: { - header: 'Получить', + header: "Получить", details: { - title: 'Покажи этот адрес плательщику', - share: 'Отправить', - copiedToClipboard: 'Скопировано', - label: 'Описание', - create: 'Создать', - setAmount: 'Получить сумму', + title: "Покажи этот адрес плательщику", + share: "Отправить", + copiedToClipboard: "Скопировано", + label: "Описание", + create: "Создать", + setAmount: "Получить сумму" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, settings: { - tabBarLabel: 'Настройки', - header: 'Настройки', - plausible_deniability: 'Правдоподобная имитация...', - storage_not_encrypted: 'Хранилище: не зашифровано', - storage_encrypted: 'Хранилище: зашифровано', - password: 'Пароль', - password_explain: 'Придумай пароль для расшифровки хранилища', - retype_password: 'Набери пароль повторно', - passwords_do_not_match: 'Пароли не совпадают', - encrypt_storage: 'Зашифровать хранилище', - lightning_settings: 'Настройки Lightning', + tabBarLabel: "Настройки", + header: "Настройки", + plausible_deniability: "Правдоподобная имитация...", + storage_not_encrypted: "Хранилище: не зашифровано", + storage_encrypted: "Хранилище: зашифровано", + password: "Пароль", + password_explain: "Придумай пароль для расшифровки хранилища", + retype_password: "Набери пароль повторно", + passwords_do_not_match: "Пароли не совпадают", + encrypt_storage: "Зашифровать хранилище", + lightning_settings: "Настройки Lightning", lightning_settings_explain: - 'Чтобы подключиться к своему узлу LND, пожалуйста, установи LndHub' + - ' и добавь его URL в настройки. Оставь поле пустым, чтобы использоавать стандартный ' + - 'LndHub\n (lndhub.io)', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Сохранить', - about: 'О программе', - language: 'Язык', - currency: 'Валюта', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "Чтобы подключиться к своему узлу LND, пожалуйста, установи LndHub" + + " и добавь его URL в настройки. Оставь поле пустым, чтобы использоавать стандартный " + + "LndHub\n (lndhub.io)", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Сохранить", + about: "О программе", + language: "Язык", + currency: "Валюта", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Правдоподобная имитация', + title: "Правдоподобная имитация", help: - 'При определенных обстоятельствах тебя могут вынудить раскрыть пароль. ' + - 'Чтобы сохранить свой Bitcoin в безопасности, Veles Wallet может создать ' + - 'еще одно зашифрованое хранилище, с другим паролем. В случае шантажа ' + - 'ты можешь раскрыть третьим лицам этот пароль. Если ввести этот пароль в ' + + "При определенных обстоятельствах тебя могут вынудить раскрыть пароль. " + + "Чтобы сохранить свой Bitcoin в безопасности, Veles Wallet может создать " + + "еще одно зашифрованое хранилище, с другим паролем. В случае шантажа " + + "ты можешь раскрыть третьим лицам этот пароль. Если ввести этот пароль в " + "Veles Wallet, разблокируется 'фальшивое' хранилище. Это будет выглядеть " + - 'правдоподобно для третьих лиц, но при этом сохранит ваше основное хранилище ' + - 'с Bitcoin в безопасности.', + "правдоподобно для третьих лиц, но при этом сохранит ваше основное хранилище " + + "с Bitcoin в безопасности.", help2: - 'Новое хранилище будет полностью функциональным и ты даже можешь хранить на нем немного Bitcoin, ' + - 'чтобы это выглядело более правдоподобно.', - create_fake_storage: 'Создать фальшивое хранилище', - go_back: 'Назад', - create_password: 'Придумай пароль', - create_password_explanation: 'Пароль для фальшивого хранилища не должен быть таким же как основной пароль', - password_should_not_match: 'Пароль для фальшивого хранилища не должен быть таким же как основной пароль', - retype_password: 'Набери пароль повторно', - passwords_do_not_match: 'Пароли не совпадают, попробуй еще раз', - success: 'Готово', + "Новое хранилище будет полностью функциональным и ты даже можешь хранить на нем немного Bitcoin, " + + "чтобы это выглядело более правдоподобно.", + create_fake_storage: "Создать фальшивое хранилище", + go_back: "Назад", + create_password: "Придумай пароль", + create_password_explanation: + "Пароль для фальшивого хранилища не должен быть таким же как основной пароль", + password_should_not_match: + "Пароль для фальшивого хранилища не должен быть таким же как основной пароль", + retype_password: "Набери пароль повторно", + passwords_do_not_match: "Пароли не совпадают, попробуй еще раз", + success: "Готово" }, lnd: { - title: 'Мои средства', - choose_source_wallet: 'Выбери с какого кошелька', - refill_lnd_balance: 'Пополнить баланс Lightning кошелька', - refill: 'Пополнить', - withdraw: 'Вывести', - expired: 'Истекший', - placeholder: 'Invoice', - sameWalletAsInvoiceError: 'Ты не можешь оплатить счет тем же кошельком, который ты использовал для его создания.', + title: "Мои средства", + choose_source_wallet: "Выбери с какого кошелька", + refill_lnd_balance: "Пополнить баланс Lightning кошелька", + refill: "Пополнить", + withdraw: "Вывести", + expired: "Истекший", + placeholder: "Invoice", + sameWalletAsInvoiceError: + "Ты не можешь оплатить счет тем же кошельком, который ты использовал для его создания." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/sv_SE.js b/loc/sv_SE.js index 68e70c25d6e..adfecf38278 100644 --- a/loc/sv_SE.js +++ b/loc/sv_SE.js @@ -1,244 +1,258 @@ module.exports = { _: { - storage_is_encrypted: 'Lagringen är krypterad. Lösenords krävs för att dekryptera', - enter_password: 'Ange lösenord', - bad_password: 'Felaktigt lösenord, försök igen', - never: 'aldrig', - continue: 'Fortsätt', - ok: 'OK', + storage_is_encrypted: + "Lagringen är krypterad. Lösenords krävs för att dekryptera", + enter_password: "Ange lösenord", + bad_password: "Felaktigt lösenord, försök igen", + never: "aldrig", + continue: "Fortsätt", + ok: "OK" }, wallets: { - select_wallet: 'Välj plånbok', - options: 'inställningar', + select_wallet: "Välj plånbok", + options: "inställningar", createBitcoinWallet: - 'Du har ännu ingen Bitcoinplånbok. För att kunna sätta in pengar i en Lightningplånbok behöver en Bitcoinplånbok skapas eller importeras. Vill du fortsätta ändå?', + "Du har ännu ingen Bitcoinplånbok. För att kunna sätta in pengar i en Lightningplånbok behöver en Bitcoinplånbok skapas eller importeras. Vill du fortsätta ändå?", list: { - app_name: 'Veles Wallet', - title: 'plånböcker', - header: 'En plånbok representerar ett par av en privat nyckel samt en adress' + 'som du kan dela med andra för att ta emot coins', - add: 'Ny Plånbok', - create_a_wallet: 'Ny plånbok', - create_a_wallet1: 'Det är gratis och du kan skapa', - create_a_wallet2: 'hur många du vill', - latest_transaction: 'senaste transaktion', - empty_txs1: 'Dina transaktioner kommer att visas här', - empty_txs2: 'men än så länge finns inga!', + app_name: "Veles Wallet", + title: "plånböcker", + header: + "En plånbok representerar ett par av en privat nyckel samt en adress" + + "som du kan dela med andra för att ta emot coins", + add: "Ny Plånbok", + create_a_wallet: "Ny plånbok", + create_a_wallet1: "Det är gratis och du kan skapa", + create_a_wallet2: "hur många du vill", + latest_transaction: "senaste transaktion", + empty_txs1: "Dina transaktioner kommer att visas här", + empty_txs2: "men än så länge finns inga!", empty_txs1_lightning: - 'Lightningplånboken ska användas för dagliga småtransaktioner. Avgifterna är minimala och transaktioner sker direkt.', - empty_txs2_lightning: '\nFör att komma igång klicka på "sätt in / ta ut" ovan och sätt in dina första bitcoin.', - tap_here_to_buy: 'Tryck här för att köpa bitcoin', + "Lightningplånboken ska användas för dagliga småtransaktioner. Avgifterna är minimala och transaktioner sker direkt.", + empty_txs2_lightning: + '\nFör att komma igång klicka på "sätt in / ta ut" ovan och sätt in dina första bitcoin.', + tap_here_to_buy: "Tryck här för att köpa bitcoin" }, reorder: { - title: 'Sortera plånböcker', + title: "Sortera plånböcker" }, add: { - title: 'ny plånbok', + title: "ny plånbok", description: - 'Du kan antingen skanna in en backup (i WIF - Wallet Import Format) eller skapa en ny plånbok. Segwit-plånböcker stöds som standard.', - scan: 'Skanna', - create: 'Skapa', - label_new_segwit: 'Ny SegWit', - label_new_lightning: 'Ny Lightning', - wallet_name: 'namn', - wallet_type: 'typ', - or: 'eller', - import_wallet: 'Importera plånbok', - imported: 'Importerad', - coming_soon: 'Kommer snart', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Du kan antingen skanna in en backup (i WIF - Wallet Import Format) eller skapa en ny plånbok. Segwit-plånböcker stöds som standard.", + scan: "Skanna", + create: "Skapa", + label_new_segwit: "Ny SegWit", + label_new_lightning: "Ny Lightning", + wallet_name: "namn", + wallet_type: "typ", + or: "eller", + import_wallet: "Importera plånbok", + imported: "Importerad", + coming_soon: "Kommer snart", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Plånbok', - address: 'Adress', - type: 'Typ', - label: 'Etikett', - description: 'beskrivning', - are_you_sure: 'Är du säker?', - yes_delete: 'Ja, ta bort', - no_cancel: 'Nej, avbryt', - delete: 'Radera', - save: 'Spara', - delete_this_wallet: 'Radera denna plånbok', - export_backup: 'Exportera / ta backup', - buy_bitcoin: 'Köp bitcoin', - show_xpub: 'Visa plånbokens XPUB', + title: "Plånbok", + address: "Adress", + type: "Typ", + label: "Etikett", + description: "beskrivning", + are_you_sure: "Är du säker?", + yes_delete: "Ja, ta bort", + no_cancel: "Nej, avbryt", + delete: "Radera", + save: "Spara", + delete_this_wallet: "Radera denna plånbok", + export_backup: "Exportera / ta backup", + buy_bitcoin: "Köp bitcoin", + show_xpub: "Visa plånbokens XPUB" }, export: { - title: 'exportera plånbok', + title: "exportera plånbok" }, xpub: { - title: 'plånbokens XPUB', - copiedToClipboard: 'Kopierad till urklipp', + title: "plånbokens XPUB", + copiedToClipboard: "Kopierad till urklipp" }, import: { - title: 'import', + title: "import", explanation: - 'Skriv in dina ord, din privata nyckel, WIF, eller vad du kan tänkas ha. Veles Wallet kommer att göra sitt bästa för att gissa formatet och importera plånboken', - imported: 'Importerad', - error: 'Import misslyckades. Kontrollera att informationen du matade in är korrekt.', - success: 'Import lyckad!', - do_import: 'Importera', - scan_qr: 'eller skanna QR-kod istället?', + "Skriv in dina ord, din privata nyckel, WIF, eller vad du kan tänkas ha. Veles Wallet kommer att göra sitt bästa för att gissa formatet och importera plånboken", + imported: "Importerad", + error: + "Import misslyckades. Kontrollera att informationen du matade in är korrekt.", + success: "Import lyckad!", + do_import: "Importera", + scan_qr: "eller skanna QR-kod istället?" }, scanQrWif: { - go_back: 'Tillbaka', - cancel: 'Avbryt', - decoding: 'Avkodar', - input_password: 'Ange lösenord', - password_explain: 'Detta är BIP38-krypterad privat nyckel', - bad_password: 'Felaktigt lösenord', - wallet_already_exists: 'En sådan plånbok existerar redan', - bad_wif: 'Felaktigt WIF', - imported_wif: 'Importerade WIF ', - with_address: ' med adress ', - imported_segwit: 'Importerade SegWit', - imported_legacy: 'Importerade Legacy', - imported_watchonly: 'Importerade Watch-only', - }, + go_back: "Tillbaka", + cancel: "Avbryt", + decoding: "Avkodar", + input_password: "Ange lösenord", + password_explain: "Detta är BIP38-krypterad privat nyckel", + bad_password: "Felaktigt lösenord", + wallet_already_exists: "En sådan plånbok existerar redan", + bad_wif: "Felaktigt WIF", + imported_wif: "Importerade WIF ", + with_address: " med adress ", + imported_segwit: "Importerade SegWit", + imported_legacy: "Importerade Legacy", + imported_watchonly: "Importerade Watch-only" + } }, transactions: { list: { - tabBarLabel: 'Transaktioner', - title: 'transaktioner', - description: 'Lista över dina plånböckers inkommande och utgående transaktioner', - conf: 'konf', + tabBarLabel: "Transaktioner", + title: "transaktioner", + description: + "Lista över dina plånböckers inkommande och utgående transaktioner", + conf: "konf" }, details: { - title: 'Transaktion', - from: 'Input', - to: 'Output', - copy: 'Kopiera', - transaction_details: 'Transaktionsdetaljer', - show_in_block_explorer: 'Visa i block explorer', - }, + title: "Transaktion", + from: "Input", + to: "Output", + copy: "Kopiera", + transaction_details: "Transaktionsdetaljer", + show_in_block_explorer: "Visa i block explorer" + } }, send: { - header: 'Skicka', + header: "Skicka", details: { - title: 'skapa transaktion', - amount_field_is_not_valid: 'Angivet belopp är inte giltigt', - fee_field_is_not_valid: 'Angiven avgift är inte giltig', - address_field_is_not_valid: 'Angiven adress är inte giltig', - total_exceeds_balance: 'Beloppet överstiger plånbokens tillgängliga belopp', - create_tx_error: 'Något gick fel när transaktionen skulle skapas. Kontrollera att adressen är giltig.', - address: 'adress', - amount_placeholder: 'belopp att skicka (i VLS)', - fee_placeholder: 'plus avgift (i VLS)', - note_placeholder: 'egen notering', - cancel: 'Avbryt', - scan: 'Skanna', - send: 'Skicka', - create: 'Skapa', - remaining_balance: 'Återstående saldo', + title: "skapa transaktion", + amount_field_is_not_valid: "Angivet belopp är inte giltigt", + fee_field_is_not_valid: "Angiven avgift är inte giltig", + address_field_is_not_valid: "Angiven adress är inte giltig", + total_exceeds_balance: + "Beloppet överstiger plånbokens tillgängliga belopp", + create_tx_error: + "Något gick fel när transaktionen skulle skapas. Kontrollera att adressen är giltig.", + address: "adress", + amount_placeholder: "belopp att skicka (i VLS)", + fee_placeholder: "plus avgift (i VLS)", + note_placeholder: "egen notering", + cancel: "Avbryt", + scan: "Skanna", + send: "Skicka", + create: "Skapa", + remaining_balance: "Återstående saldo" }, confirm: { - header: 'Bekräfta', - sendNow: 'Skicka nu', + header: "Bekräfta", + sendNow: "Skicka nu" }, success: { - done: 'Klart!', + done: "Klart!" }, create: { - details: 'Detaljer', - title: 'skapa transaktion', - error: 'Något gick fel när transaktionen skulle skapas. Felaktig adress eller belopp?', - go_back: 'Tillbaka', - this_is_hex: 'Detta är transaktionens hex, signerad och redo att skickas ut på nätverket.', - to: 'Till', - amount: 'Belopp', - fee: 'Avgift', - tx_size: 'Transaktionsstorlek', - satoshi_per_byte: 'Satoshi per byte', - memo: 'Memo', - broadcast: 'Publicera', - not_enough_fee: 'För låg avgift. Öka avgiften', - }, + details: "Detaljer", + title: "skapa transaktion", + error: + "Något gick fel när transaktionen skulle skapas. Felaktig adress eller belopp?", + go_back: "Tillbaka", + this_is_hex: + "Detta är transaktionens hex, signerad och redo att skickas ut på nätverket.", + to: "Till", + amount: "Belopp", + fee: "Avgift", + tx_size: "Transaktionsstorlek", + satoshi_per_byte: "Satoshi per byte", + memo: "Memo", + broadcast: "Publicera", + not_enough_fee: "För låg avgift. Öka avgiften" + } }, receive: { - header: 'Ta emot', + header: "Ta emot", details: { - title: 'Dela den här adressen med betalaren', - share: 'dela', - copiedToClipboard: 'Kopierad till urklipp.', - label: 'Beskrivning', - create: 'Skapa', - setAmount: 'Ta emot med belopp', + title: "Dela den här adressen med betalaren", + share: "dela", + copiedToClipboard: "Kopierad till urklipp.", + label: "Beskrivning", + create: "Skapa", + setAmount: "Ta emot med belopp" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Köp bitcoin', - tap_your_address: 'Tryck på adressen för att kopiera den till urklipp:', - copied: 'Kopierad till urklipp!', + header: "Köp bitcoin", + tap_your_address: "Tryck på adressen för att kopiera den till urklipp:", + copied: "Kopierad till urklipp!" }, settings: { - header: 'inställningar', - plausible_deniability: 'Trovärdigt förnekande...', - storage_not_encrypted: 'Lagring: ej krypterad', - storage_encrypted: 'Lagring: krypterad', - password: 'Lösenord', - password_explain: 'Skapa ett lösenord som du kommer att använda vid dekryptering', - retype_password: 'Ange lösenord igen', - passwords_do_not_match: 'Lösenorden är olika!', - encrypt_storage: 'Kryptera lagring', - lightning_settings: 'Lightning Network', + header: "inställningar", + plausible_deniability: "Trovärdigt förnekande...", + storage_not_encrypted: "Lagring: ej krypterad", + storage_encrypted: "Lagring: krypterad", + password: "Lösenord", + password_explain: + "Skapa ett lösenord som du kommer att använda vid dekryptering", + retype_password: "Ange lösenord igen", + passwords_do_not_match: "Lösenorden är olika!", + encrypt_storage: "Kryptera lagring", + lightning_settings: "Lightning Network", lightning_settings_explain: - 'För att ansluta till din egen LND-nod, installera LndHub' + + "För att ansluta till din egen LND-nod, installera LndHub" + " och mata in dess URL nedan. Lämna blankt för att använda Veles Wallet's LNDHub (lndhub.io). Plånböcker skapade efter att inställningarna sparats kommer att använda den angivna LNDHub:en", - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Spara', - about: 'Om', - language: 'Språk', - currency: 'Valuta', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Spara", + about: "Om", + language: "Språk", + currency: "Valuta", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Trovärdigt förnekande', + title: "Trovärdigt förnekande", help: - 'Under vissa omständigheter kan du bli tvingad att uppge ditt ' + - 'lösenord. För att se till att dina pengar är säkra kan Veles Wallet skapa ytterligare en ' + - 'krypterad lagringsyta, med ett annat lösenord. Vid tvång ' + - 'kan du uppge detta alternativa lösenord. När det matas in i ' + + "Under vissa omständigheter kan du bli tvingad att uppge ditt " + + "lösenord. För att se till att dina pengar är säkra kan Veles Wallet skapa ytterligare en " + + "krypterad lagringsyta, med ett annat lösenord. Vid tvång " + + "kan du uppge detta alternativa lösenord. När det matas in i " + "Veles Wallet så kommer det att låsa upp din 'fejkade' lagringsyta. Det kommer att se " + - 'ut precis som vanligt men i själva verket är dina pengar i säkert förvar på din ' + - 'primära lagringsyta.', + "ut precis som vanligt men i själva verket är dina pengar i säkert förvar på din " + + "primära lagringsyta.", help2: - 'Den alternativa lagringsytan kommer att vara fullt fungerade och du kan eventuellt spara en mindre summa där för att den ska verka mer trovärdig.', - create_fake_storage: 'Skapa fejkad lagringsyta', - go_back: 'Tillbaka', - create_password: 'Skapa ett lösenord', - create_password_explanation: 'Lösenordet för den fejkade lagringsytan får inte vara samma som ditt huvudlösenord', - password_should_not_match: 'Lösenordet för den fejkade lagringsytan får inte vara samma som ditt huvudlösenord', - retype_password: 'Ange lösenord igen', - passwords_do_not_match: 'Lösenorden är olika!', - success: 'Fejkad lagringsyta skapad!', + "Den alternativa lagringsytan kommer att vara fullt fungerade och du kan eventuellt spara en mindre summa där för att den ska verka mer trovärdig.", + create_fake_storage: "Skapa fejkad lagringsyta", + go_back: "Tillbaka", + create_password: "Skapa ett lösenord", + create_password_explanation: + "Lösenordet för den fejkade lagringsytan får inte vara samma som ditt huvudlösenord", + password_should_not_match: + "Lösenordet för den fejkade lagringsytan får inte vara samma som ditt huvudlösenord", + retype_password: "Ange lösenord igen", + passwords_do_not_match: "Lösenorden är olika!", + success: "Fejkad lagringsyta skapad!" }, lnd: { - title: 'sätt in / ta ut', - choose_source_wallet: 'Välj en plånbok', - refill_lnd_balance: 'Fyll på Lightning-plånbok', - refill: 'Sätt in', - withdraw: 'Ta ut', - expired: 'Förfallen', - placeholder: 'Faktura', - sameWalletAsInvoiceError: 'Du kan inte betala en faktura från samma plånbok som användes för att skapa den.', + title: "sätt in / ta ut", + choose_source_wallet: "Välj en plånbok", + refill_lnd_balance: "Fyll på Lightning-plånbok", + refill: "Sätt in", + withdraw: "Ta ut", + expired: "Förfallen", + placeholder: "Faktura", + sameWalletAsInvoiceError: + "Du kan inte betala en faktura från samma plånbok som användes för att skapa den." }, pleasebackup: { - title: 'Din plånbok har skapats...', + title: "Din plånbok har skapats...", text: - 'Innan du går vidare, var snäll och skriv ned dessa ord på ett papper och förvara på ett säkert ställe. De är din backup och säkerställer att du kan återställa din plånbok igen om något händer.', - ok: 'OK, jag har skrivit ned orden!', + "Innan du går vidare, var snäll och skriv ned dessa ord på ett papper och förvara på ett säkert ställe. De är din backup och säkerställer att du kan återställa din plånbok igen om något händer.", + ok: "OK, jag har skrivit ned orden!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'Denna faktura har ej betalats och är nu utgången', - has_been_paid: 'Denna faktura är betald', - please_pay: 'Var god betala', - sats: 'sats', - for: 'För:', - additional_info: 'Ytterligare information', - open_direct_channel: 'Öppna en direkt kanal med denna nod:', - }, + wasnt_paid_and_expired: "Denna faktura har ej betalats och är nu utgången", + has_been_paid: "Denna faktura är betald", + please_pay: "Var god betala", + sats: "sats", + for: "För:", + additional_info: "Ytterligare information", + open_direct_channel: "Öppna en direkt kanal med denna nod:" + } }; diff --git a/loc/th_TH.js b/loc/th_TH.js index 5341445e01d..7f376429dfd 100644 --- a/loc/th_TH.js +++ b/loc/th_TH.js @@ -1,243 +1,257 @@ module.exports = { _: { - storage_is_encrypted: 'ที่เก็บข้อมูลของคุณถูกเข้ารหัส. ต้องการรหัสผ่านเพื่อถอดรหัส', - enter_password: 'กรุณาใส่รหัสผ่าน', - bad_password: 'รหัสผ่านไม่ถูกต้อง กรุณาใส่รหัสผ่านอีกครั้ง', - never: 'ไม่เคย', - continue: 'ต่อไป', - ok: 'ตกลง', + storage_is_encrypted: + "ที่เก็บข้อมูลของคุณถูกเข้ารหัส. ต้องการรหัสผ่านเพื่อถอดรหัส", + enter_password: "กรุณาใส่รหัสผ่าน", + bad_password: "รหัสผ่านไม่ถูกต้อง กรุณาใส่รหัสผ่านอีกครั้ง", + never: "ไม่เคย", + continue: "ต่อไป", + ok: "ตกลง" }, wallets: { - select_wallet: 'เลือกกระเป๋าสตางค์', - options: 'ทางเลือก', + select_wallet: "เลือกกระเป๋าสตางค์", + options: "ทางเลือก", createBitcoinWallet: - 'ในการใช้งานกระเป๋าสตางค์ไลท์นิง คุณจำเป็นต้องมีกระเป๋าสตางค์บิตคอยน์. คุณต้องการสร้างกระเป๋าสตางค์บิตคอยน์หรือไม่?', + "ในการใช้งานกระเป๋าสตางค์ไลท์นิง คุณจำเป็นต้องมีกระเป๋าสตางค์บิตคอยน์. คุณต้องการสร้างกระเป๋าสตางค์บิตคอยน์หรือไม่?", list: { - app_name: 'บูลวอลเล็ต', - title: 'กระเป๋าสตางค์', - header: 'กระเป๋าสตางค์คือที่เก็บไพร์เวทคีย์และแอดเดรส' + 'ที่คุณสามารถแชร์เพื่อโอนรับเหรียญ.', - add: 'เพิ่มกระเป๋าสตางค์', - create_a_wallet: 'สร้างกระเป๋าสตางค์', - create_a_wallet1: 'ไม่มีค่าใช้จ่าย และคุณสามารถสร้างกระเป๋าสตางค์', - create_a_wallet2: 'ได้มากเท่าที่ต้องการ', - latest_transaction: 'ธุรกรรมล่าสุด', - empty_txs1: 'ธุรกรรมจะปรากฏที่นี่,', - empty_txs2: 'ไม่มี ณ ขณะนี้', - empty_txs1_lightning: 'ควรใช้ไลท์นิงเน็ตเวิร์คสำหรับธุรกรรมประจำวันเท่านั้น ธุรกรรมทันใจและมีค่าธรรมเนียมน้อยมาก', - empty_txs2_lightning: '\nแตะที่ "จัดการเงิน" เพื่อเริ่มใช้งาน และเติมเงิน', - tap_here_to_buy: 'กดที่นี่เพื่อซื้อบิตคอยน์', + app_name: "บูลวอลเล็ต", + title: "กระเป๋าสตางค์", + header: + "กระเป๋าสตางค์คือที่เก็บไพร์เวทคีย์และแอดเดรส" + + "ที่คุณสามารถแชร์เพื่อโอนรับเหรียญ.", + add: "เพิ่มกระเป๋าสตางค์", + create_a_wallet: "สร้างกระเป๋าสตางค์", + create_a_wallet1: "ไม่มีค่าใช้จ่าย และคุณสามารถสร้างกระเป๋าสตางค์", + create_a_wallet2: "ได้มากเท่าที่ต้องการ", + latest_transaction: "ธุรกรรมล่าสุด", + empty_txs1: "ธุรกรรมจะปรากฏที่นี่,", + empty_txs2: "ไม่มี ณ ขณะนี้", + empty_txs1_lightning: + "ควรใช้ไลท์นิงเน็ตเวิร์คสำหรับธุรกรรมประจำวันเท่านั้น ธุรกรรมทันใจและมีค่าธรรมเนียมน้อยมาก", + empty_txs2_lightning: + '\nแตะที่ "จัดการเงิน" เพื่อเริ่มใช้งาน และเติมเงิน', + tap_here_to_buy: "กดที่นี่เพื่อซื้อบิตคอยน์" }, reorder: { - title: 'เปลี่ยนลำดับกระเป๋าสตางค์', + title: "เปลี่ยนลำดับกระเป๋าสตางค์" }, add: { - title: 'เพิ่มกระเป๋าสตางค์', + title: "เพิ่มกระเป๋าสตางค์", description: - 'คุณสามรถสแกนกระเป๋าสตางค์กระดาษ(ในรูปแบบ WIF - Wallet Import Format), หรือสร้างกระเป๋าสตางค์ใหม่. กระเป๋าสตางค์ใหม่จะใช้ Segwit โดยอัตโนมัติ.', - scan: 'สแกน', - create: 'สร้าง', - label_new_segwit: 'SegWit ใหม่', - label_new_lightning: 'ไลท์นิงใหม่', - wallet_name: 'ชื่อกระเป๋าสตางค์', - wallet_type: 'ชนิด', - or: 'หรือ', - import_wallet: 'นำเข้ากระเป๋าสตางค์', - imported: 'นำเข้าแล้ว', - coming_soon: 'เร็วๆนี้', - lightning: 'ไลท์นิง', - bitcoin: 'บิตคอยน์', + "คุณสามรถสแกนกระเป๋าสตางค์กระดาษ(ในรูปแบบ WIF - Wallet Import Format), หรือสร้างกระเป๋าสตางค์ใหม่. กระเป๋าสตางค์ใหม่จะใช้ Segwit โดยอัตโนมัติ.", + scan: "สแกน", + create: "สร้าง", + label_new_segwit: "SegWit ใหม่", + label_new_lightning: "ไลท์นิงใหม่", + wallet_name: "ชื่อกระเป๋าสตางค์", + wallet_type: "ชนิด", + or: "หรือ", + import_wallet: "นำเข้ากระเป๋าสตางค์", + imported: "นำเข้าแล้ว", + coming_soon: "เร็วๆนี้", + lightning: "ไลท์นิง", + bitcoin: "บิตคอยน์" }, details: { - title: 'กระเป๋าสตางค์', - address: 'แอดเดรส', - type: 'ชนิด', - label: 'ป้าย', - destination: 'เป้าหมาย', - description: 'คำอธิบาย', - are_you_sure: 'คุณแน่ใจหรือไม่?', - yes_delete: 'ใช่, ลบเลย', - no_cancel: 'ไม่ใช่, ยกเลิก', - delete: 'ลบ', - save: 'เก็บ', - delete_this_wallet: 'ลบกระเป๋าสตางค์อันนี้', - export_backup: 'ส่งออก / สำรอง', - buy_bitcoin: 'ซื้อบิตคอยน์', - show_xpub: 'แสดง XPUB ของกระเป๋าสตางค์', + title: "กระเป๋าสตางค์", + address: "แอดเดรส", + type: "ชนิด", + label: "ป้าย", + destination: "เป้าหมาย", + description: "คำอธิบาย", + are_you_sure: "คุณแน่ใจหรือไม่?", + yes_delete: "ใช่, ลบเลย", + no_cancel: "ไม่ใช่, ยกเลิก", + delete: "ลบ", + save: "เก็บ", + delete_this_wallet: "ลบกระเป๋าสตางค์อันนี้", + export_backup: "ส่งออก / สำรอง", + buy_bitcoin: "ซื้อบิตคอยน์", + show_xpub: "แสดง XPUB ของกระเป๋าสตางค์" }, export: { - title: 'ส่งออกกระเป๋าสตางค์', + title: "ส่งออกกระเป๋าสตางค์" }, xpub: { - title: 'XPUB ของกระเป๋าสตางค์', - copiedToClipboard: 'ก๊อปปี้ไปที่คลิปบอร์ดแล้ว.', + title: "XPUB ของกระเป๋าสตางค์", + copiedToClipboard: "ก๊อปปี้ไปที่คลิปบอร์ดแล้ว." }, import: { - title: 'นำเข้า', - explanation: 'บันทึกนีโมนิค(สิ่งที่ช่วยให้จำได้), ไพร์เวทคีย์, WIF, และทุกๆอย่าง. บูลวอลเล็ทจะพยายามนำเข้ากระเป๋าสตางค์ของคุณ', - imported: 'นำเข้าแล้ว', - error: 'ไม่สามารถนำเข้าได้. กรุณาตรวจสอบข้อมูลให้ถูกต้อง.', - success: 'สำเร็จ', - do_import: 'นำเข้า', - scan_qr: 'หรือสแกนรหัสคิวอาร์แทน?', + title: "นำเข้า", + explanation: + "บันทึกนีโมนิค(สิ่งที่ช่วยให้จำได้), ไพร์เวทคีย์, WIF, และทุกๆอย่าง. บูลวอลเล็ทจะพยายามนำเข้ากระเป๋าสตางค์ของคุณ", + imported: "นำเข้าแล้ว", + error: "ไม่สามารถนำเข้าได้. กรุณาตรวจสอบข้อมูลให้ถูกต้อง.", + success: "สำเร็จ", + do_import: "นำเข้า", + scan_qr: "หรือสแกนรหัสคิวอาร์แทน?" }, scanQrWif: { - go_back: 'กลับ', - cancel: 'ยกเลิก', - decoding: 'กำลังถอดรหัส', - input_password: 'ใส่รหัสผ่าน', - password_explain: 'นี่คือไพร์เวทคีย์ที่เข้ารหัสแบบ BIP38', - bad_password: 'รหัสไม่ถูกต้อง', - wallet_already_exists: 'กระเป๋าสตางค์นี้มีอยู่แล้ว', - bad_wif: 'WIF ไม่ถูกต้อง', - imported_wif: 'WIF ที่นำเข้า', - with_address: ' ด้วยแอดเดรส ', - imported_segwit: 'SegWit ที่นำเข้า', - imported_legacy: 'Legacy ที่นำเข้า', - imported_watchonly: 'Watch-only ที่นำเข้า', - }, + go_back: "กลับ", + cancel: "ยกเลิก", + decoding: "กำลังถอดรหัส", + input_password: "ใส่รหัสผ่าน", + password_explain: "นี่คือไพร์เวทคีย์ที่เข้ารหัสแบบ BIP38", + bad_password: "รหัสไม่ถูกต้อง", + wallet_already_exists: "กระเป๋าสตางค์นี้มีอยู่แล้ว", + bad_wif: "WIF ไม่ถูกต้อง", + imported_wif: "WIF ที่นำเข้า", + with_address: " ด้วยแอดเดรส ", + imported_segwit: "SegWit ที่นำเข้า", + imported_legacy: "Legacy ที่นำเข้า", + imported_watchonly: "Watch-only ที่นำเข้า" + } }, transactions: { list: { - tabBarLabel: 'ธุรกรรม', - title: 'ธุรกรรม', - description: 'รายการธุรกรรมเข้าออกของกระเป๋าสตางค์ของคุณ', - conf: 'conf', + tabBarLabel: "ธุรกรรม", + title: "ธุรกรรม", + description: "รายการธุรกรรมเข้าออกของกระเป๋าสตางค์ของคุณ", + conf: "conf" }, details: { - title: 'ธุรกรรม', - from: 'อินพุท', - to: 'เอ้าพุท', - copy: 'ก๊อปปี้', - transaction_details: 'รายละเอียดธุรกรรม', - show_in_block_explorer: 'แสดงด้วย block explorer', - }, + title: "ธุรกรรม", + from: "อินพุท", + to: "เอ้าพุท", + copy: "ก๊อปปี้", + transaction_details: "รายละเอียดธุรกรรม", + show_in_block_explorer: "แสดงด้วย block explorer" + } }, send: { - header: 'ส่ง', + header: "ส่ง", details: { - title: 'สร้างธุรกรรม', - amount_field_is_not_valid: 'จำนวนเงินไม่ถูกต้อง', - fee_field_is_not_valid: 'ค่าธรรมเนียมไม่ถูกต้อง', - address_field_is_not_valid: 'แอดเดรสไม่ถูกต้อง', - total_exceeds_balance: 'จำนวนเงินที่จะส่งเกินเงินที่มี.', - create_tx_error: 'ไม่สามารถสร้างธุรกรรมได้. กรุณาตรวจสอบแอดเดรสให้ถูกต้อง.', - address: 'แอดเดรส', - amount_placeholder: 'จำนวนเงินที่ส่ง (หน่วย VLS)', - fee_placeholder: 'รวมค่าธรรมเนียม (หน่วย VLS)', - note_placeholder: 'หมายเหตุถึงตัวท่านเอง', - cancel: 'ยกเลิก', - scan: 'สแกน', - send: 'ส่ง', - create: 'สร้าง', - remaining_balance: 'ยอดคงเหลือ', + title: "สร้างธุรกรรม", + amount_field_is_not_valid: "จำนวนเงินไม่ถูกต้อง", + fee_field_is_not_valid: "ค่าธรรมเนียมไม่ถูกต้อง", + address_field_is_not_valid: "แอดเดรสไม่ถูกต้อง", + total_exceeds_balance: "จำนวนเงินที่จะส่งเกินเงินที่มี.", + create_tx_error: + "ไม่สามารถสร้างธุรกรรมได้. กรุณาตรวจสอบแอดเดรสให้ถูกต้อง.", + address: "แอดเดรส", + amount_placeholder: "จำนวนเงินที่ส่ง (หน่วย VLS)", + fee_placeholder: "รวมค่าธรรมเนียม (หน่วย VLS)", + note_placeholder: "หมายเหตุถึงตัวท่านเอง", + cancel: "ยกเลิก", + scan: "สแกน", + send: "ส่ง", + create: "สร้าง", + remaining_balance: "ยอดคงเหลือ" }, confirm: { - header: 'ยืนยัน', - sendNow: 'ส่งเดี๋ยวนี้', + header: "ยืนยัน", + sendNow: "ส่งเดี๋ยวนี้" }, success: { - done: 'สำเร็จ', + done: "สำเร็จ" }, create: { - details: 'รายละเอียด', - title: 'สร้างธุรกรรม', - error: 'ไม่สามารถสร้างธุรกรรมได้. แอดเดรสไม่ถูกต้อง หรือ จำนวนเงินไม่ถูกต้อง?', - go_back: 'กลับ', - this_is_hex: 'นี่คือ hex ของธุรกรรม, signed แล้วและพร้อมที่จะบรอดคาซท์ไปยังเน็ตเวิร์ค.', - to: 'ถึง', - amount: 'จำนวนเงิน', - fee: 'ค่าธรรมเนียม', - tx_size: 'ขนาดธุรกรรม', - satoshi_per_byte: 'ซาโตชิต่อไบท์', - memo: 'บันทึกช่วยจำ', - broadcast: 'บรอดคาซท์', - not_enough_fee: 'ค่าธรรมเนียมไม่เพียงพอ. กรุณาเพิ่มค่าธรรมเนียม', - }, + details: "รายละเอียด", + title: "สร้างธุรกรรม", + error: + "ไม่สามารถสร้างธุรกรรมได้. แอดเดรสไม่ถูกต้อง หรือ จำนวนเงินไม่ถูกต้อง?", + go_back: "กลับ", + this_is_hex: + "นี่คือ hex ของธุรกรรม, signed แล้วและพร้อมที่จะบรอดคาซท์ไปยังเน็ตเวิร์ค.", + to: "ถึง", + amount: "จำนวนเงิน", + fee: "ค่าธรรมเนียม", + tx_size: "ขนาดธุรกรรม", + satoshi_per_byte: "ซาโตชิต่อไบท์", + memo: "บันทึกช่วยจำ", + broadcast: "บรอดคาซท์", + not_enough_fee: "ค่าธรรมเนียมไม่เพียงพอ. กรุณาเพิ่มค่าธรรมเนียม" + } }, receive: { - header: 'รับ', + header: "รับ", details: { - title: 'แชร์แอดเดรสนี้กับผู้จ่าย', - share: 'แชร์', - copiedToClipboard: 'ก๊อปปี้ไปที่คลิปบอร์ดแล้ว.', - label: 'คำอธิบาย', - create: 'สร้าง', - setAmount: 'รับด้วยจำนวน', + title: "แชร์แอดเดรสนี้กับผู้จ่าย", + share: "แชร์", + copiedToClipboard: "ก๊อปปี้ไปที่คลิปบอร์ดแล้ว.", + label: "คำอธิบาย", + create: "สร้าง", + setAmount: "รับด้วยจำนวน" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'ซื้อบิตคอยน์', - tap_your_address: 'กดที่แอดเดรสของคุณเพื่อก๊อปปี้ไปยังคลิปบอร์ด:', - copied: 'ก๊อปปี้ไปที่คลิปบอร์ดแล้ว!', + header: "ซื้อบิตคอยน์", + tap_your_address: "กดที่แอดเดรสของคุณเพื่อก๊อปปี้ไปยังคลิปบอร์ด:", + copied: "ก๊อปปี้ไปที่คลิปบอร์ดแล้ว!" }, settings: { - header: 'ตั้งค่า', - plausible_deniability: 'การปฏิเสธที่เป็นไปได้...', - storage_not_encrypted: 'ที่เก็บข้อมูล: ยังไม่เข้ารหัส', - storage_encrypted: 'ที่เก็บข้อมูล: เข้ารหัสแล้ว', - password: 'รหัสผ่าน', - password_explain: 'สร้างรหัสผ่านที่จะใช้ในการเข้ารหัสที่เก็บข้อมูล', - retype_password: 'ใส่รหัสผ่านอีกครั้ง', - passwords_do_not_match: 'รหัสผ่านไม่ตรงกัน', - encrypt_storage: 'เข้ารหัสที่เก็บข้อมูล', - lightning_settings: 'การตั้งค่าไลท์นิง', + header: "ตั้งค่า", + plausible_deniability: "การปฏิเสธที่เป็นไปได้...", + storage_not_encrypted: "ที่เก็บข้อมูล: ยังไม่เข้ารหัส", + storage_encrypted: "ที่เก็บข้อมูล: เข้ารหัสแล้ว", + password: "รหัสผ่าน", + password_explain: "สร้างรหัสผ่านที่จะใช้ในการเข้ารหัสที่เก็บข้อมูล", + retype_password: "ใส่รหัสผ่านอีกครั้ง", + passwords_do_not_match: "รหัสผ่านไม่ตรงกัน", + encrypt_storage: "เข้ารหัสที่เก็บข้อมูล", + lightning_settings: "การตั้งค่าไลท์นิง", lightning_settings_explain: - 'กรณีที่ต้องการต่อเชื่อมไปยังไลท์นิงโนดของท่านเอง กรุณาติดตั้ง LndHub ของท่าน' + - ' และไส่ URL ที่นี่. ระบบจะใช้ LndHub ของ lndhub.io ในกรณืที่ท่าน ' + - ' ไม่ตั้งค่าใดๆ', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'บันทึก', - about: 'เกี่ยวกับ', - language: 'ภาษา', - currency: 'เงินตรา', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "กรณีที่ต้องการต่อเชื่อมไปยังไลท์นิงโนดของท่านเอง กรุณาติดตั้ง LndHub ของท่าน" + + " และไส่ URL ที่นี่. ระบบจะใช้ LndHub ของ lndhub.io ในกรณืที่ท่าน " + + " ไม่ตั้งค่าใดๆ", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "บันทึก", + about: "เกี่ยวกับ", + language: "ภาษา", + currency: "เงินตรา", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'การปฏิเสธที่เป็นไปได้', + title: "การปฏิเสธที่เป็นไปได้", help: - 'ภายใต้บางสถานการ์ณ, คุณอาจจะจำเป็นต้องเปิดเผย' + - 'รหัสผ่าน. เพื่อเก็บเหรียญให้ปลอดถัย บูลวอลเล็ทสามารถสร้างที่เก็บข้อมูล' + - 'อีกแห่งหนึ่งโดยใช้รหัสผ่านคนละอัน. ภายใต้สถานการ์ณที่จำเป็น ' + - 'คุณสามารถเปิดเลยรหัสผ่านนี้กับบุคคลที่สาม. และเมื่อใส่รหัสผ่านนี้ใน ' + - 'บลูวอลเล็ท ที่เก็บข้อมูลเทียมจะถูกเปิด. และ' + - 'น่าจะเป็นที่ยอมรับได้ต่อบุคลที่สาม, วิธีนี้จะทำให้ที่เก็บข้อมูลหลักมีความปลอดภัย' + - 'และเป็นความลับ.', - help2: 'ที่เก็บข้อมูลอันใหม่จะทำงานได้สมบูรณ์ และคุณสามารถเก็บจำนวนเงินขั้นต่ำได้ ' + 'โดยที่มีความน่าเชื่อถือ.', - create_fake_storage: 'สร้างที่เก็บข้อมูลเทียม', - go_back: 'กลับ', - create_password: 'สร้างรหัสผ่าน', - create_password_explanation: 'รหัสผ่านสำหรับที่เก็บข้อมูลเทียมไม่ควรตรงกับรหัสผ่านที่ใช้กับที่เก็บข้อมูลเทียมจริง', - password_should_not_match: 'รหัสผ่านสำหรับที่เก็บข้อมูลเทียมไม่ควรตรงกับรหัสผ่านที่ใช้กับที่เก็บข้อมูลเทียมจริง', - retype_password: 'ใส่รหัสผ่านอีกครั้ง ใส่รหัสผ่านอีกครั้ง', - passwords_do_not_match: 'รหัสผ่านไม่ตรงกัน ', - success: 'สำเร็จ', + "ภายใต้บางสถานการ์ณ, คุณอาจจะจำเป็นต้องเปิดเผย" + + "รหัสผ่าน. เพื่อเก็บเหรียญให้ปลอดถัย บูลวอลเล็ทสามารถสร้างที่เก็บข้อมูล" + + "อีกแห่งหนึ่งโดยใช้รหัสผ่านคนละอัน. ภายใต้สถานการ์ณที่จำเป็น " + + "คุณสามารถเปิดเลยรหัสผ่านนี้กับบุคคลที่สาม. และเมื่อใส่รหัสผ่านนี้ใน " + + "บลูวอลเล็ท ที่เก็บข้อมูลเทียมจะถูกเปิด. และ" + + "น่าจะเป็นที่ยอมรับได้ต่อบุคลที่สาม, วิธีนี้จะทำให้ที่เก็บข้อมูลหลักมีความปลอดภัย" + + "และเป็นความลับ.", + help2: + "ที่เก็บข้อมูลอันใหม่จะทำงานได้สมบูรณ์ และคุณสามารถเก็บจำนวนเงินขั้นต่ำได้ " + + "โดยที่มีความน่าเชื่อถือ.", + create_fake_storage: "สร้างที่เก็บข้อมูลเทียม", + go_back: "กลับ", + create_password: "สร้างรหัสผ่าน", + create_password_explanation: + "รหัสผ่านสำหรับที่เก็บข้อมูลเทียมไม่ควรตรงกับรหัสผ่านที่ใช้กับที่เก็บข้อมูลเทียมจริง", + password_should_not_match: + "รหัสผ่านสำหรับที่เก็บข้อมูลเทียมไม่ควรตรงกับรหัสผ่านที่ใช้กับที่เก็บข้อมูลเทียมจริง", + retype_password: "ใส่รหัสผ่านอีกครั้ง ใส่รหัสผ่านอีกครั้ง", + passwords_do_not_match: "รหัสผ่านไม่ตรงกัน ", + success: "สำเร็จ" }, lnd: { - title: 'จัดการเงิน', - choose_source_wallet: 'เลือกกระเป๋าสตางค์', - refill_lnd_balance: 'เติมกระเป๋าสตางค์ไลท์นิง', - refill: 'เติม', - withdraw: 'ถอน', - placeholder: 'ใบวางบิล', - expired: 'หมดอายุแล้ว', - sameWalletAsInvoiceError: 'คุณไม่สามารถจ่ายใบแจ้งหนี้นี้ด้วยกระเป๋าสตางค์อันเดียวกันกับที่ใช้สร้างมัน.', + title: "จัดการเงิน", + choose_source_wallet: "เลือกกระเป๋าสตางค์", + refill_lnd_balance: "เติมกระเป๋าสตางค์ไลท์นิง", + refill: "เติม", + withdraw: "ถอน", + placeholder: "ใบวางบิล", + expired: "หมดอายุแล้ว", + sameWalletAsInvoiceError: + "คุณไม่สามารถจ่ายใบแจ้งหนี้นี้ด้วยกระเป๋าสตางค์อันเดียวกันกับที่ใช้สร้างมัน." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/tr_TR.js b/loc/tr_TR.js index 680bc489eaf..1b7b9cd5e7a 100644 --- a/loc/tr_TR.js +++ b/loc/tr_TR.js @@ -1,244 +1,256 @@ module.exports = { _: { - storage_is_encrypted: 'Your storage is encrypted. Password is required to decrypt it', - enter_password: 'Şifre gir', - bad_password: 'Hatalı şifre, tekrar deneyin', - never: 'asla', - continue: 'Devam et', - ok: 'Tamam', + storage_is_encrypted: + "Your storage is encrypted. Password is required to decrypt it", + enter_password: "Şifre gir", + bad_password: "Hatalı şifre, tekrar deneyin", + never: "asla", + continue: "Devam et", + ok: "Tamam" }, wallets: { - select_wallet: 'Cüzdan Seç', - options: 'seçenekler', + select_wallet: "Cüzdan Seç", + options: "seçenekler", createBitcoinWallet: - 'Şu anda Bitcoin cüzdanınız yok. Lightning cüzdanına yükleme yapmak için Bitcoin cüzdanı oluşturmak veya içeri yüklemek gerekir. Yine de devam etmek istiyor musunuz?', + "Şu anda Bitcoin cüzdanınız yok. Lightning cüzdanına yükleme yapmak için Bitcoin cüzdanı oluşturmak veya içeri yüklemek gerekir. Yine de devam etmek istiyor musunuz?", list: { - app_name: 'Veles Wallet', - title: 'cüzdanlar', - header: 'Cüzdan biri gizli, biri halka açık olan bir çift anahtar ve koin almak için' + ' paylaşabileceğiniz bir adrestir.', - add: 'Cüzdan Ekle', - create_a_wallet: 'Cüzdan oluştur', - create_a_wallet1: 'Oluşturması bedava ve', - create_a_wallet2: 'istediğiniz kadar oluşturabilirsiniz', - latest_transaction: 'en son işlem', - empty_txs1: 'İşlemleriniz burada görünür,', - empty_txs2: 'şu anda hiç yok', + app_name: "Veles Wallet", + title: "cüzdanlar", + header: + "Cüzdan biri gizli, biri halka açık olan bir çift anahtar ve koin almak için" + + " paylaşabileceğiniz bir adrestir.", + add: "Cüzdan Ekle", + create_a_wallet: "Cüzdan oluştur", + create_a_wallet1: "Oluşturması bedava ve", + create_a_wallet2: "istediğiniz kadar oluşturabilirsiniz", + latest_transaction: "en son işlem", + empty_txs1: "İşlemleriniz burada görünür,", + empty_txs2: "şu anda hiç yok", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Bitcoin almak için buraya dokunun', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Bitcoin almak için buraya dokunun" }, reorder: { - title: 'Cüzdanları Sırala', + title: "Cüzdanları Sırala" }, add: { - title: 'cüzdan ekle', + title: "cüzdan ekle", description: - 'Kağıt cüzdan (WIF - Wallet Import Format olarak) tarayarak içeri yükleyebilirsiniz veya cüzdan oluşturabilirsiniz. Segwit cüzdanlar standard olarak desteklenir.', - scan: 'Tara', - create: 'Oluştur', - label_new_segwit: 'Yeni SegWit', - label_new_lightning: 'Yeni Lightning', - wallet_name: 'isim', - wallet_type: 'tip', - or: 'veya', - import_wallet: 'Cüzdan İçeri Yükle', - imported: 'Yüklendi', - coming_soon: 'Yakında', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + "Kağıt cüzdan (WIF - Wallet Import Format olarak) tarayarak içeri yükleyebilirsiniz veya cüzdan oluşturabilirsiniz. Segwit cüzdanlar standard olarak desteklenir.", + scan: "Tara", + create: "Oluştur", + label_new_segwit: "Yeni SegWit", + label_new_lightning: "Yeni Lightning", + wallet_name: "isim", + wallet_type: "tip", + or: "veya", + import_wallet: "Cüzdan İçeri Yükle", + imported: "Yüklendi", + coming_soon: "Yakında", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Cüzdan', - address: 'Adres', - type: 'Tip', - label: 'Etiket', - destination: 'hedef', - description: 'tanım', - are_you_sure: 'Emin misiniz?', - yes_delete: 'Evet, sil', - no_cancel: 'Hayır, vazgeç', - delete: 'Sil', - save: 'Kaydet', - delete_this_wallet: 'Bu cüzdanı sil', - export_backup: 'Dışa yükle / yedekle', - buy_bitcoin: 'Bitcoin satın al', - show_xpub: 'Cüzdan XPUB göster', + title: "Cüzdan", + address: "Adres", + type: "Tip", + label: "Etiket", + destination: "hedef", + description: "tanım", + are_you_sure: "Emin misiniz?", + yes_delete: "Evet, sil", + no_cancel: "Hayır, vazgeç", + delete: "Sil", + save: "Kaydet", + delete_this_wallet: "Bu cüzdanı sil", + export_backup: "Dışa yükle / yedekle", + buy_bitcoin: "Bitcoin satın al", + show_xpub: "Cüzdan XPUB göster" }, export: { - title: 'cüzdan yedekle', + title: "cüzdan yedekle" }, xpub: { - title: 'cüzdan XPUB', - copiedToClipboard: 'Panoya kopyalandı', + title: "cüzdan XPUB", + copiedToClipboard: "Panoya kopyalandı" }, import: { - title: 'içeri yükle', + title: "içeri yükle", explanation: - 'Buraya cüzdan yedek cümlenizi, gizli anahtarınızı, WIF veya diğer bilginizi yazın. Veles Wallet elinden gelen en iyi tahmini yaparak cüzdanınızı içeri aktarmaya çalışacak.', - imported: 'İçeri aktarıldı', - error: 'İçeri aktarma başarısız oldu. Lütfen girilen bilginin doğru olduğundan emin olun.', - success: 'Başarılı', - do_import: 'İçe Aktar', - scan_qr: 'veya QR kod tara?', + "Buraya cüzdan yedek cümlenizi, gizli anahtarınızı, WIF veya diğer bilginizi yazın. Veles Wallet elinden gelen en iyi tahmini yaparak cüzdanınızı içeri aktarmaya çalışacak.", + imported: "İçeri aktarıldı", + error: + "İçeri aktarma başarısız oldu. Lütfen girilen bilginin doğru olduğundan emin olun.", + success: "Başarılı", + do_import: "İçe Aktar", + scan_qr: "veya QR kod tara?" }, scanQrWif: { - go_back: 'Geri Git', - cancel: 'Vazgeç', - decoding: 'Deşifre ediliyor', - input_password: 'Şifre gir', - password_explain: 'Bu BIP38 şifreli gizli anahtar', - bad_password: 'Hatalı şifre', - wallet_already_exists: 'Böyle bir cüzdan zaten var', - bad_wif: 'Hatalı WIF', - imported_wif: 'İçeri aktarılmış WIF ', - with_address: ' adres ile ', - imported_segwit: 'İçeri Aktarılmış SegWit', - imported_legacy: 'İçeri Aktarılmış Eski Tip', - imported_watchonly: 'İçeri Aktarılmış Sadece-izleme', - }, + go_back: "Geri Git", + cancel: "Vazgeç", + decoding: "Deşifre ediliyor", + input_password: "Şifre gir", + password_explain: "Bu BIP38 şifreli gizli anahtar", + bad_password: "Hatalı şifre", + wallet_already_exists: "Böyle bir cüzdan zaten var", + bad_wif: "Hatalı WIF", + imported_wif: "İçeri aktarılmış WIF ", + with_address: " adres ile ", + imported_segwit: "İçeri Aktarılmış SegWit", + imported_legacy: "İçeri Aktarılmış Eski Tip", + imported_watchonly: "İçeri Aktarılmış Sadece-izleme" + } }, transactions: { list: { - tabBarLabel: 'İşlemler', - title: 'işlemler', - description: 'Cüzdanlarınıza gelen ve giden işlemlerin bir listesi', - conf: 'onay', + tabBarLabel: "İşlemler", + title: "işlemler", + description: "Cüzdanlarınıza gelen ve giden işlemlerin bir listesi", + conf: "onay" }, details: { - title: 'İşlem', - from: 'Girdi', - to: 'Çıktı', - copy: 'Kopya', - transaction_details: 'İşlem detayları', - show_in_block_explorer: 'Blok gezgininde göster', - }, + title: "İşlem", + from: "Girdi", + to: "Çıktı", + copy: "Kopya", + transaction_details: "İşlem detayları", + show_in_block_explorer: "Blok gezgininde göster" + } }, send: { - header: 'Gönder', + header: "Gönder", details: { - title: 'işlem oluştur', - amount_field_is_not_valid: 'Miktar alanı geçerli değil', - fee_field_is_not_valid: 'Ücret alanı geçerli değil', - address_field_is_not_valid: 'Adres alanı geçerli değil', - total_exceeds_balance: 'Gönderme miktarı mevcut bakiyeyi aşıyor.', - create_tx_error: 'İşlem oluşturulurken bir hata oluştu. Lütfen adresin geçerli olduğundan emin olun.', - address: 'adres', - amount_placeholder: 'gönderilecek miktar (VLS cinsinden)', - fee_placeholder: 'artı işlem ücreti (VLS cinsinden)', - note_placeholder: 'kendime not', - cancel: 'Vazgeç', - scan: 'Tara', - send: 'Gönder', - create: 'Oluştur', - remaining_balance: 'Kalan bakiye', + title: "işlem oluştur", + amount_field_is_not_valid: "Miktar alanı geçerli değil", + fee_field_is_not_valid: "Ücret alanı geçerli değil", + address_field_is_not_valid: "Adres alanı geçerli değil", + total_exceeds_balance: "Gönderme miktarı mevcut bakiyeyi aşıyor.", + create_tx_error: + "İşlem oluşturulurken bir hata oluştu. Lütfen adresin geçerli olduğundan emin olun.", + address: "adres", + amount_placeholder: "gönderilecek miktar (VLS cinsinden)", + fee_placeholder: "artı işlem ücreti (VLS cinsinden)", + note_placeholder: "kendime not", + cancel: "Vazgeç", + scan: "Tara", + send: "Gönder", + create: "Oluştur", + remaining_balance: "Kalan bakiye" }, confirm: { - header: 'Onayla', - sendNow: 'Şimdi gönder', + header: "Onayla", + sendNow: "Şimdi gönder" }, success: { - done: 'Tamam', + done: "Tamam" }, create: { - details: 'Detaylar', - title: 'işlem oluştur', - error: 'İşlem yaratma hatası. Geçersiz adres veya gönderim miktarı?', - go_back: 'Geri dön', - this_is_hex: 'Bu işlemin hexi, imzalanmış ve ağa yayınlanmaya hazır.', - to: 'Kime', - amount: 'Miktar', - fee: 'Ücret', - tx_size: 'TX boyutu', - satoshi_per_byte: 'Bayt başına Satoshi', - memo: 'Not', - broadcast: 'Yayınla', - not_enough_fee: 'Yetersiz ücret. Ücreti arttırın', - }, + details: "Detaylar", + title: "işlem oluştur", + error: "İşlem yaratma hatası. Geçersiz adres veya gönderim miktarı?", + go_back: "Geri dön", + this_is_hex: "Bu işlemin hexi, imzalanmış ve ağa yayınlanmaya hazır.", + to: "Kime", + amount: "Miktar", + fee: "Ücret", + tx_size: "TX boyutu", + satoshi_per_byte: "Bayt başına Satoshi", + memo: "Not", + broadcast: "Yayınla", + not_enough_fee: "Yetersiz ücret. Ücreti arttırın" + } }, receive: { - header: 'Al', + header: "Al", details: { - title: 'Bu adresi ödeyenle paylaş', - share: 'paylaş', - copiedToClipboard: 'Panoya kopyalandı.', - label: 'Açıklama', - create: 'Oluştur', - setAmount: 'Miktar ile al', + title: "Bu adresi ödeyenle paylaş", + share: "paylaş", + copiedToClipboard: "Panoya kopyalandı.", + label: "Açıklama", + create: "Oluştur", + setAmount: "Miktar ile al" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Bitcoin Satın al', - tap_your_address: 'Panoya kopyalamak için adresinize dokunun:', - copied: 'Panoya kopyalandı!', + header: "Bitcoin Satın al", + tap_your_address: "Panoya kopyalamak için adresinize dokunun:", + copied: "Panoya kopyalandı!" }, settings: { - header: 'ayarlar', - plausible_deniability: 'Makul ret...', - storage_not_encrypted: 'Depolama: şifreli değil', - storage_encrypted: 'Depolama: şifreli', - password: 'Şifre', - password_explain: 'Depolamanın şifresini çözmek için kullanacağınız şifreyi oluşturun', - retype_password: 'Şifrenizi yeniden girin', - passwords_do_not_match: 'Şifreler eşleşmedi', - encrypt_storage: 'Depolamayı şifrele', - lightning_settings: 'Lightning Ayarları', + header: "ayarlar", + plausible_deniability: "Makul ret...", + storage_not_encrypted: "Depolama: şifreli değil", + storage_encrypted: "Depolama: şifreli", + password: "Şifre", + password_explain: + "Depolamanın şifresini çözmek için kullanacağınız şifreyi oluşturun", + retype_password: "Şifrenizi yeniden girin", + passwords_do_not_match: "Şifreler eşleşmedi", + encrypt_storage: "Depolamayı şifrele", + lightning_settings: "Lightning Ayarları", lightning_settings_explain: - 'Kendi LND düğümünüze bağlanmak için lütfen LndHubı yükleyin.' + + "Kendi LND düğümünüze bağlanmak için lütfen LndHubı yükleyin." + " ve URL’sini buraya, ayarlara yazın. Veles Wallet'in LNDHub (lndhub.io) programını kullanmak için boş bırakın. Değişiklikleri kaydettikten sonra oluşturulan cüzdanlar belirtilen LNDHub'a bağlanacaktır.", - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'Kaydet', - about: 'Hakkında', - language: 'Dil', - currency: 'Para Birimi', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "Kaydet", + about: "Hakkında", + language: "Dil", + currency: "Para Birimi", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Makul Ret', + title: "Makul Ret", help: - 'Bazı koşullar altında, şifrenizi açıklamanız gerekebilir. ' + - 'Paralarınızı güvende tutmak için, Veles Wallet başka bir şifre ile ' + - 'şifreli depolama alanı yaratabilir. Baskı altında, ' + - 'Bu şifreyi 3. bir tarafa söyleyebilirsiniz. Girilirse ' + + "Bazı koşullar altında, şifrenizi açıklamanız gerekebilir. " + + "Paralarınızı güvende tutmak için, Veles Wallet başka bir şifre ile " + + "şifreli depolama alanı yaratabilir. Baskı altında, " + + "Bu şifreyi 3. bir tarafa söyleyebilirsiniz. Girilirse " + "Veles Wallet, yeni 'sahte' bir depolamanın kilidini açacaktır. Bu 3. şahıslara " + - 'normal görünecektir, ancak paraların olduğu ana depolama alanınızı gizlice saklamaya ' + - 'devam edecektir.', - help2: 'Yeni depolama alanı tamamen işlevsel olacak ve ufak ' + 'bir miktar tutarsanız daha inanılır görünecektir.', - create_fake_storage: 'Sahte şifreli depolama oluşturun', - go_back: 'Geri Dön', - create_password: 'Şifre oluştur', - create_password_explanation: 'Sahte depolama şifreniz, ana depolama şifrenizle aynı olmamalıdır.', - password_should_not_match: 'Sahte depolama şifreniz, ana depolama şifrenizle aynı olmamalıdır', - retype_password: 'Şifrenizi yeniden yazın', - passwords_do_not_match: 'Şifreler eşleşmedi, tekrar dene', - success: 'Başarılı', + "normal görünecektir, ancak paraların olduğu ana depolama alanınızı gizlice saklamaya " + + "devam edecektir.", + help2: + "Yeni depolama alanı tamamen işlevsel olacak ve ufak " + + "bir miktar tutarsanız daha inanılır görünecektir.", + create_fake_storage: "Sahte şifreli depolama oluşturun", + go_back: "Geri Dön", + create_password: "Şifre oluştur", + create_password_explanation: + "Sahte depolama şifreniz, ana depolama şifrenizle aynı olmamalıdır.", + password_should_not_match: + "Sahte depolama şifreniz, ana depolama şifrenizle aynı olmamalıdır", + retype_password: "Şifrenizi yeniden yazın", + passwords_do_not_match: "Şifreler eşleşmedi, tekrar dene", + success: "Başarılı" }, lnd: { - title: 'paraları yönet', - choose_source_wallet: 'Kaynak bir cüzdan seçin', - refill_lnd_balance: 'Lightning cüzdana bakiye yükle', - refill: 'Yükle', - withdraw: 'Çek', - expired: 'Süresi doldu', - placeholder: 'Fatura', - sameWalletAsInvoiceError: 'Bir faturayı, oluştururken kullandığınız cüzdan ile ödeyemezsiniz.', + title: "paraları yönet", + choose_source_wallet: "Kaynak bir cüzdan seçin", + refill_lnd_balance: "Lightning cüzdana bakiye yükle", + refill: "Yükle", + withdraw: "Çek", + expired: "Süresi doldu", + placeholder: "Fatura", + sameWalletAsInvoiceError: + "Bir faturayı, oluştururken kullandığınız cüzdan ile ödeyemezsiniz." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/ua.js b/loc/ua.js index 0bdc72736e6..4992c61eb77 100644 --- a/loc/ua.js +++ b/loc/ua.js @@ -1,248 +1,259 @@ module.exports = { _: { - storage_is_encrypted: 'Ваше сховище зашифроване. Введіть пароль для розшифровки', - enter_password: 'Введіть пароль', - bad_password: 'Невірний пароль, спробуйте ще раз', - never: 'ніколи', - continue: 'Continue', - ok: 'OK', + storage_is_encrypted: + "Ваше сховище зашифроване. Введіть пароль для розшифровки", + enter_password: "Введіть пароль", + bad_password: "Невірний пароль, спробуйте ще раз", + never: "ніколи", + continue: "Continue", + ok: "OK" }, wallets: { - options: 'options', - select_wallet: 'Select Wallet', - createBitcoinWallet: 'In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?', + options: "options", + select_wallet: "Select Wallet", + createBitcoinWallet: + "In order to use a Lightning wallet, a Bitcoin wallet is needed to fund it. Would you like to continue anyway?", list: { - app_name: 'Veles Wallet', - title: 'гаманці', - header: 'Гаманець це секретний (приватний) ключ, і відповідна йому адреса на яку можна отримувати біткоїни', - add: 'Додати Гаманець', - create_a_wallet: 'Створити гаманець', - create_a_wallet1: 'Це безкоштовно і можно', - create_a_wallet2: 'створювати безліч', - latest_transaction: 'остання транзакція', + app_name: "Veles Wallet", + title: "гаманці", + header: + "Гаманець це секретний (приватний) ключ, і відповідна йому адреса на яку можна отримувати біткоїни", + add: "Додати Гаманець", + create_a_wallet: "Створити гаманець", + create_a_wallet1: "Це безкоштовно і можно", + create_a_wallet2: "створювати безліч", + latest_transaction: "остання транзакція", empty_txs1: "Транзакціі з'являться тут,", - empty_txs2: 'поки що жодноі', + empty_txs2: "поки що жодноі", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: 'Tap here to buy Bitcoin', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "Tap here to buy Bitcoin" }, reorder: { - title: 'Reorder Wallets', + title: "Reorder Wallets" }, add: { - title: 'Додати Гаманець', + title: "Додати Гаманець", description: - 'Ви можете відсканувати QR код (у форматі WIF - Wallet Import Format), або створити новий гаманець. Segwit підтримується за умовчанням.', - scan: 'Відсканувати', - create: 'Створити', - label_new_segwit: 'Новий SegWit', - label_new_lightning: 'Новий Lightning', + "Ви можете відсканувати QR код (у форматі WIF - Wallet Import Format), або створити новий гаманець. Segwit підтримується за умовчанням.", + scan: "Відсканувати", + create: "Створити", + label_new_segwit: "Новий SegWit", + label_new_lightning: "Новий Lightning", wallet_name: "ім'я гаманця", - wallet_type: 'тип гаманця', - or: 'чи', - import_wallet: 'імпортувати гаманець', - imported: 'імпортовано', - coming_soon: 'Буде скоро', - lightning: 'Lightning', - bitcoin: 'Bitcoin', + wallet_type: "тип гаманця", + or: "чи", + import_wallet: "імпортувати гаманець", + imported: "імпортовано", + coming_soon: "Буде скоро", + lightning: "Lightning", + bitcoin: "Bitcoin" }, details: { - title: 'Інформація про Гаманець', - address: 'Адреса', - type: 'Тип', - delete: 'Delete', - save: 'Save', - label: 'Мітка', - destination: 'destination', - description: 'description', - are_you_sure: 'Ви впевнені?', - yes_delete: 'Так, видалити', - no_cancel: 'Ні, відміна', - delete_this_wallet: 'Видалити цей гаманець', - export_backup: 'Експорт / резервна копія', - buy_bitcoin: 'Buy Bitcoin', - show_xpub: 'Show wallet XPUB', + title: "Інформація про Гаманець", + address: "Адреса", + type: "Тип", + delete: "Delete", + save: "Save", + label: "Мітка", + destination: "destination", + description: "description", + are_you_sure: "Ви впевнені?", + yes_delete: "Так, видалити", + no_cancel: "Ні, відміна", + delete_this_wallet: "Видалити цей гаманець", + export_backup: "Експорт / резервна копія", + buy_bitcoin: "Buy Bitcoin", + show_xpub: "Show wallet XPUB" }, export: { - title: 'Експорт Гаманця', + title: "Експорт Гаманця" }, xpub: { - title: 'wallet XPUB', - copiedToClipboard: 'Зкопіювано', + title: "wallet XPUB", + copiedToClipboard: "Зкопіювано" }, import: { - title: 'імпорт', - explanation: 'Мнемоніка, приватний ключ, чи будь що. Veles Wallet спробуе вгадати вірний формат', - imported: 'імпортовано', - error: 'Невдача. Це взашалі валідно?', - success: 'Успіх', - do_import: 'імпорт', - scan_qr: 'чи сканувати QR?', + title: "імпорт", + explanation: + "Мнемоніка, приватний ключ, чи будь що. Veles Wallet спробуе вгадати вірний формат", + imported: "імпортовано", + error: "Невдача. Це взашалі валідно?", + success: "Успіх", + do_import: "імпорт", + scan_qr: "чи сканувати QR?" }, scanQrWif: { - go_back: 'Назад', - cancel: 'Відміна', - decoding: 'Декодую', - input_password: 'Введіть пароль', - password_explain: 'Приватний ключ зашифрований за стандартом Bip38', - bad_password: 'Невірний пароль', - wallet_already_exists: 'Такий гаманець вже існує', - bad_wif: 'Некоректний WIF', - imported_wif: 'Імпортовано WIF ', - with_address: ' з адресою ', - imported_segwit: 'Імпортований SegWit', - imported_legacy: 'Імпортований Legacy', - imported_watchonly: 'Імпортовано Watch-only', - }, + go_back: "Назад", + cancel: "Відміна", + decoding: "Декодую", + input_password: "Введіть пароль", + password_explain: "Приватний ключ зашифрований за стандартом Bip38", + bad_password: "Невірний пароль", + wallet_already_exists: "Такий гаманець вже існує", + bad_wif: "Некоректний WIF", + imported_wif: "Імпортовано WIF ", + with_address: " з адресою ", + imported_segwit: "Імпортований SegWit", + imported_legacy: "Імпортований Legacy", + imported_watchonly: "Імпортовано Watch-only" + } }, transactions: { list: { - tabBarLabel: 'Транзакції', - title: 'Мої транзакції', - description: 'Список вхідних або вихідних транзакцій ваших гаманців', - conf: 'підтв.', + tabBarLabel: "Транзакції", + title: "Мої транзакції", + description: "Список вхідних або вихідних транзакцій ваших гаманців", + conf: "підтв." }, details: { - title: 'Деталі транзакції', - from: 'Від', - to: 'Кому', - copy: 'копія', - transaction_details: 'Transaction details', - show_in_block_explorer: 'Show in block explorer', - }, + title: "Деталі транзакції", + from: "Від", + to: "Кому", + copy: "копія", + transaction_details: "Transaction details", + show_in_block_explorer: "Show in block explorer" + } }, send: { - header: 'Переказ', + header: "Переказ", details: { - title: 'Створити Транзакцію', - amount_field_is_not_valid: 'Поле не валідно', - fee_field_is_not_valid: 'Поле `комісія` не валідно', - address_field_is_not_valid: 'Поле `адреса` не валідно', - receiver_placeholder: 'Адреса одержувача', - amount_placeholder: 'скільки відправити (в VLS)', - fee_placeholder: 'плюс комісія за переказ (в VLS)', - create_tx_error: 'There was an error creating the transaction. Please, make sure the address is valid.', - note_placeholder: 'примітка платежу', - cancel: 'Відміна', - scan: 'Скан QR', - send: 'Send', - total_exceeds_balance: 'total_exceeds_balance', - address: 'Address', - create: 'Створити', - remaining_balance: 'Залишок балансу', + title: "Створити Транзакцію", + amount_field_is_not_valid: "Поле не валідно", + fee_field_is_not_valid: "Поле `комісія` не валідно", + address_field_is_not_valid: "Поле `адреса` не валідно", + receiver_placeholder: "Адреса одержувача", + amount_placeholder: "скільки відправити (в VLS)", + fee_placeholder: "плюс комісія за переказ (в VLS)", + create_tx_error: + "There was an error creating the transaction. Please, make sure the address is valid.", + note_placeholder: "примітка платежу", + cancel: "Відміна", + scan: "Скан QR", + send: "Send", + total_exceeds_balance: "total_exceeds_balance", + address: "Address", + create: "Створити", + remaining_balance: "Залишок балансу" }, confirm: { - header: 'Confirm', - sendNow: 'Send now', + header: "Confirm", + sendNow: "Send now" }, success: { - done: 'Done', + done: "Done" }, create: { - title: 'Створити Транзакцію', - details: 'Details', - error: 'Помилка при створенні транзакції. Невiрна адреса призначення або недостатньо коштiв?', - go_back: 'Назад', - this_is_hex: 'Це дані транзакції. Транзакція підписана і готова бути трансльована в мережу. Продовжити?', - to: 'Куди', - amount: 'Скільки', - fee: 'Комісія', - tx_size: 'Розмір', - satoshi_per_byte: 'Сатоші на байт', - memo: 'Примітка', - broadcast: 'Відправити', - not_enough_fee: 'Недостатньо комісіі. Збільште комісію', - }, + title: "Створити Транзакцію", + details: "Details", + error: + "Помилка при створенні транзакції. Невiрна адреса призначення або недостатньо коштiв?", + go_back: "Назад", + this_is_hex: + "Це дані транзакції. Транзакція підписана і готова бути трансльована в мережу. Продовжити?", + to: "Куди", + amount: "Скільки", + fee: "Комісія", + tx_size: "Розмір", + satoshi_per_byte: "Сатоші на байт", + memo: "Примітка", + broadcast: "Відправити", + not_enough_fee: "Недостатньо комісіі. Збільште комісію" + } }, receive: { - header: 'Отримати', + header: "Отримати", details: { - title: 'Покажіть цю адресу платникові', - share: 'Відправити', - copiedToClipboard: 'Зкопіювано', - label: 'Description', - create: 'Create', - setAmount: 'Receive with amount', + title: "Покажіть цю адресу платникові", + share: "Відправити", + copiedToClipboard: "Зкопіювано", + label: "Description", + create: "Create", + setAmount: "Receive with amount" }, - scan_lnurl: 'Scan to receive', + scan_lnurl: "Scan to receive" }, buyBitcoin: { - header: 'Buy Bitcoin', - tap_your_address: 'Tap your address to copy it to clipboard:', - copied: 'Copied to Clipboard!', + header: "Buy Bitcoin", + tap_your_address: "Tap your address to copy it to clipboard:", + copied: "Copied to Clipboard!" }, settings: { - tabBarLabel: 'Налаштування', - header: 'Налаштування', - plausible_deniability: 'Правдоподібне заперечення...', - storage_not_encrypted: 'Сховище: не зашифровано', - storage_encrypted: 'Сховище: зашифровано', - password: 'Пароль', - password_explain: 'Придумайте пароль для розшифровки сховища', - retype_password: 'Наберіть пароль ще раз', - passwords_do_not_match: 'Паролі не збігаються', - encrypt_storage: 'Зашифрувати сховище', - lightning_settings: 'Lightning settings', + tabBarLabel: "Налаштування", + header: "Налаштування", + plausible_deniability: "Правдоподібне заперечення...", + storage_not_encrypted: "Сховище: не зашифровано", + storage_encrypted: "Сховище: зашифровано", + password: "Пароль", + password_explain: "Придумайте пароль для розшифровки сховища", + retype_password: "Наберіть пароль ще раз", + passwords_do_not_match: "Паролі не збігаються", + encrypt_storage: "Зашифрувати сховище", + lightning_settings: "Lightning settings", lightning_settings_explain: - 'To connect to your own LND node please install LndHub' + - ' and put its URL here in settings. Leave blank to use default ' + - 'ndHub\n (lndhub.io)', - electrum_settings: 'Electrum Settings', - electrum_settings_explain: 'Set to blank to use default', - save: 'save', - about: 'Про програму', - language: 'Мова', - currency: 'Валюта', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + "To connect to your own LND node please install LndHub" + + " and put its URL here in settings. Leave blank to use default " + + "ndHub\n (lndhub.io)", + electrum_settings: "Electrum Settings", + electrum_settings_explain: "Set to blank to use default", + save: "save", + about: "Про програму", + language: "Мова", + currency: "Валюта", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: 'Правдоподібне Заперечення', + title: "Правдоподібне Заперечення", help: - 'При певних обставинах вас можуть змусити розкрити пароль. ' + - 'Щоб зберегти ваші біткоїни в безпеці, Veles Wallet може створити ' + - 'ще одне зашифроване сховище, з іншим паролем. Під тиском, ' + - 'ви можете розкрити третім особам цей пароль. Якщо ввести цей пароль ' + + "При певних обставинах вас можуть змусити розкрити пароль. " + + "Щоб зберегти ваші біткоїни в безпеці, Veles Wallet може створити " + + "ще одне зашифроване сховище, з іншим паролем. Під тиском, " + + "ви можете розкрити третім особам цей пароль. Якщо ввести цей пароль " + "Veles Wallet, розблоковується 'фальшиве' сховище. Це виглядатиме " + - 'правдоподібно для третіх осіб, але при цьому збереже ваше основне сховище ' + - 'з біткоїнамі в безпеці.', + "правдоподібно для третіх осіб, але при цьому збереже ваше основне сховище " + + "з біткоїнамі в безпеці.", help2: - 'Нове сховище буде повністю функціональним і ви навіть можете зберігати на ньому небагато біткоїнов ' + - 'щоб це виглядало правдоподібніше.', - create_fake_storage: 'Створити фальшиве сховище', - go_back: 'Назад', - create_password: 'Придумайте пароль', - create_password_explanation: 'Пароль для фальшивого сховіща не має буті таким же як основній пароль', - password_should_not_match: 'Пароль для фальшивого сховища не має бути таким же як основний пароль', - retype_password: 'Наберіть пароль ще раз', - passwords_do_not_match: 'Паролі не збігаються, спробуйте ще раз', - success: 'Операція успішна', + "Нове сховище буде повністю функціональним і ви навіть можете зберігати на ньому небагато біткоїнов " + + "щоб це виглядало правдоподібніше.", + create_fake_storage: "Створити фальшиве сховище", + go_back: "Назад", + create_password: "Придумайте пароль", + create_password_explanation: + "Пароль для фальшивого сховіща не має буті таким же як основній пароль", + password_should_not_match: + "Пароль для фальшивого сховища не має бути таким же як основний пароль", + retype_password: "Наберіть пароль ще раз", + passwords_do_not_match: "Паролі не збігаються, спробуйте ще раз", + success: "Операція успішна" }, lnd: { - title: 'мої кошти', - choose_source_wallet: 'Оберіть гаманець с якого слати', - refill_lnd_balance: 'Збільшити баланс Lightning гаманця', - refill: 'Поповнити', - placeholder: 'Invoice', - withdraw: 'Вивести', - expired: 'Expired', - sameWalletAsInvoiceError: 'You can not pay an invoice with the same wallet used to create it.', + title: "мої кошти", + choose_source_wallet: "Оберіть гаманець с якого слати", + refill_lnd_balance: "Збільшити баланс Lightning гаманця", + refill: "Поповнити", + placeholder: "Invoice", + withdraw: "Вивести", + expired: "Expired", + sameWalletAsInvoiceError: + "You can not pay an invoice with the same wallet used to create it." }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/loc/vi_VN.js b/loc/vi_VN.js index 027c83e2ace..0188fb71eed 100644 --- a/loc/vi_VN.js +++ b/loc/vi_VN.js @@ -1,20 +1,23 @@ module.exports = { _: { - storage_is_encrypted: "Lưu trữ của bạn được mã hoá. Mật khẩu được yêu cầu để giải mã", + storage_is_encrypted: + "Lưu trữ của bạn được mã hoá. Mật khẩu được yêu cầu để giải mã", enter_password: "Nhập mật khẩu", bad_password: "Mật khẩu sai, vui lòng thử lại", never: "không bao giờ", continue: "Tiếp tục", - ok: "OK", + ok: "OK" }, wallets: { select_wallet: "Chọn Ví", options: "lựa chọn", - createBitcoinWallet: "Hiện giờ quý khách không có Ví bitcoin. Để trả tiền cho ví Lightning, một ví Bitcoin cần được tạo hoặc nhập. Quý khách có muốn tiếp tục không?", + createBitcoinWallet: + "Hiện giờ quý khách không có Ví bitcoin. Để trả tiền cho ví Lightning, một ví Bitcoin cần được tạo hoặc nhập. Quý khách có muốn tiếp tục không?", list: { app_name: "Veles Wallet", title: "ví", - header: "Một ví đại diện cho cặp khóa bí mật ( khóa riêng tư) và một địa chỉ quý khách có thể chia sẻ để nhận tiền xu", + header: + "Một ví đại diện cho cặp khóa bí mật ( khóa riêng tư) và một địa chỉ quý khách có thể chia sẻ để nhận tiền xu", add: "Thêm Ví", create_a_wallet: "Tạo ví", create_a_wallet1: "Miễn phí và quý khách có thể tạo", @@ -22,16 +25,19 @@ module.exports = { latest_transaction: "giao dịch gần đây nhất", empty_txs1: "Giao dịch của quý khách sẽ xuất hiện tại đây.", empty_txs2: "không có tại thời điểm hiện tại", - empty_txs1_lightning: "Ví Lightning nên được sử dụng cho giao dịch hàng ngày của quý khách. Phí rẻ và tốc độ nhanh", - empty_txs2_lightning: "\n Để bắt đầu sử dụng nó chạm vào \"quản lý tiền\" và thêm tiền vào số dư của quý khách", - tap_here_to_buy: "Chạm vào đây để mua Bitcoin", + empty_txs1_lightning: + "Ví Lightning nên được sử dụng cho giao dịch hàng ngày của quý khách. Phí rẻ và tốc độ nhanh", + empty_txs2_lightning: + '\n Để bắt đầu sử dụng nó chạm vào "quản lý tiền" và thêm tiền vào số dư của quý khách', + tap_here_to_buy: "Chạm vào đây để mua Bitcoin" }, reorder: { - title: "Đặt hàng lại Ví ", + title: "Đặt hàng lại Ví " }, add: { title: "thêm ví", - description: "Quý khách có thể quét mặt sau của ví( ở WIF - Định dạng nhập Ví) hoặc tạo ví mới, Segwwit được hỗ trợ mặc định", + description: + "Quý khách có thể quét mặt sau của ví( ở WIF - Định dạng nhập Ví) hoặc tạo ví mới, Segwwit được hỗ trợ mặc định", scan: "Quét", create: "Tạo'", label_new_segwit: "Segwit mới", @@ -43,7 +49,7 @@ module.exports = { imported: "Đã nhập", coming_soon: "Sắp tới", lightning: "Lightning ", - bitcoin: "Veles", + bitcoin: "Veles" }, details: { title: "Ví", @@ -60,23 +66,25 @@ module.exports = { delete_this_wallet: "Xóa ví này", export_backup: "Xuất/ mặt sau", buy_bitcoin: "Mua Bitcoin", - show_xpub: "Hiện ví XPUB", + show_xpub: "Hiện ví XPUB" }, export: { - title: "xuất ví", + title: "xuất ví" }, xpub: { title: "ví XPUB", - copiedToClipboard: "Sao chép đến clipboard", + copiedToClipboard: "Sao chép đến clipboard" }, import: { title: "nhập", - explanation: "Viết ở đây bản ghi nhớ, khóa riêng, WIF hoặc bất cứ thứ gì quý khách có. Veles Wallet sẽ cố hết sức để đoán đúng định dạng và nhập ví của quý khách", + explanation: + "Viết ở đây bản ghi nhớ, khóa riêng, WIF hoặc bất cứ thứ gì quý khách có. Veles Wallet sẽ cố hết sức để đoán đúng định dạng và nhập ví của quý khách", imported: "Đã nhập", - error: "Không thể nhập. Xin vui lòng đảm bảo rằng dữ liệu quý khách cung cấp là hợp lệ", + error: + "Không thể nhập. Xin vui lòng đảm bảo rằng dữ liệu quý khách cung cấp là hợp lệ", success: "Thành công", do_import: "Nhập", - scan_qr: "hoặc quét mã QR?", + scan_qr: "hoặc quét mã QR?" }, scanQrWif: { go_back: "Trở lại", @@ -91,15 +99,16 @@ module.exports = { with_address: "với địa chỉ", imported_segwit: "Nhập Segwit", imported_legacy: "Nhập Legacy", - imported_watchonly: "Nhập watch-only", - }, + imported_watchonly: "Nhập watch-only" + } }, transactions: { list: { tabBarLabel: "Giao dịch", title: "giao dịch", - description: "Danh sách các giao dịch đang được thực hiện hoặc gửi đi từ ví của quý khách ", - conf: "conf", + description: + "Danh sách các giao dịch đang được thực hiện hoặc gửi đi từ ví của quý khách ", + conf: "conf" }, details: { title: "Giao dịch", @@ -107,20 +116,21 @@ module.exports = { to: "Đến", copy: "Sao chép", transaction_details: "Chi tiết giao dịch", - show_in_block_explorer: "Xem ở block explorer", - }, + show_in_block_explorer: "Xem ở block explorer" + } }, send: { header: "Gửi", success: { - done: "Hoàn thành", + done: "Hoàn thành" }, details: { title: "tạo giao dịch", amount_field_is_not_valid: "Số lượng không hợp lệ", fee_field_is_not_valid: "Phí không hợp lệ", address_field_is_not_valid: "Địa chỉ không hợp lệ", - create_tx_error: "Đã xảy ra lỗi khi tạo giao dịch. Xin vui lòng đảm bảo rằng địa chỉ ví hợp lệ", + create_tx_error: + "Đã xảy ra lỗi khi tạo giao dịch. Xin vui lòng đảm bảo rằng địa chỉ ví hợp lệ", address: "địa chỉ", amount_placeholder: "số tiền gửi ( bằng VLS)", fee_placeholder: "cộng thêm phí giao dịch ( bằng VLS)", @@ -130,18 +140,20 @@ module.exports = { send: "Gửi", create: "tạo hóa đơn", remaining_balance: "Số dư còn lại", - total_exceeds_balance: "Số tiền gửi vượt quá số dư khả dụng", + total_exceeds_balance: "Số tiền gửi vượt quá số dư khả dụng" }, confirm: { header: "Xác nhận", - sendNow: "Gửi ngay bây giờ", + sendNow: "Gửi ngay bây giờ" }, create: { details: "Chi tiết", title: "tạo giao dịch", - error: "Xảy ra lỗi khi tạo giao dịch. Địa chỉ không hợp lệ hoặc gửi tiền?", + error: + "Xảy ra lỗi khi tạo giao dịch. Địa chỉ không hợp lệ hoặc gửi tiền?", go_back: "Quay lại", - this_is_hex: "Đây là giao dịch hex, đăng ký và chuẩn bị được phát lên mạng", + this_is_hex: + "Đây là giao dịch hex, đăng ký và chuẩn bị được phát lên mạng", to: "Đến", amount: "Số lượng", fee: "Phí", @@ -149,8 +161,8 @@ module.exports = { satoshi_per_byte: "Satoshi mỗi byte", memo: "Memo", broadcast: "Phát sóng", - not_enough_fee: "Không đủ phí. Tăng phí", - }, + not_enough_fee: "Không đủ phí. Tăng phí" + } }, receive: { header: "Nhận", @@ -160,14 +172,15 @@ module.exports = { copiedToClipboard: "Sao chép đến clipboard", label: "Miêu tả", create: "Tạo", - setAmount: "Nhận với số lượng", + setAmount: "Nhận với số lượng" }, - scan_lnurl: "Quét để nhận", + scan_lnurl: "Quét để nhận" }, buyBitcoin: { header: "Mua Bitcoin", - tap_your_address: "Chạm vào địa chỉ của quý khách để sao chép đến clipboard", - copied: "Sao chép đếnClipboard", + tap_your_address: + "Chạm vào địa chỉ của quý khách để sao chép đến clipboard", + copied: "Sao chép đếnClipboard" }, settings: { header: "cài đặt", @@ -175,7 +188,8 @@ module.exports = { storage_not_encrypted: "Lưu trữ không được mã hóa", storage_encrypted: "Lưu trữ được mã hóa", password: "Mật khẩu", - password_explain: "Tạo mật khẩu cái mà quý khách sẽ sử dụng để giải mã hóa bộ nhớ", + password_explain: + "Tạo mật khẩu cái mà quý khách sẽ sử dụng để giải mã hóa bộ nhớ", retype_password: "Nhập lại mật khẩu", passwords_do_not_match: "Mật khẩu không khớp", encrypt_storage: "Giải mã bộ nhớ", @@ -187,20 +201,24 @@ module.exports = { language: "Ngôn ngữ", currency: "Tiền tệ", advanced_options: "Tùy chọn nâng cao", - enable_advanced_mode: "Kích hoạt chế độ nâng cao", + enable_advanced_mode: "Kích hoạt chế độ nâng cao" }, plausibledeniability: { title: "Từ chối hợp lý", - help: "Trong một số trường hợp nhất định, quý khách có thể bắt buộc phải tiết lộ mật khẩu. Để giữ tiền xu của quý khách được an toàn, Veles Wallet có thể tạo một bộ lưu trữ được mã hóa khác, với một mật khẩu khác. Dưới áp lực, quý khách có thể tiết lộ mật khẩu này cho bên thứ ba. Nếu được nhập vào Veles Wallet, nó sẽ mở khóa bộ nhớ giả mới. Điều này có vẻ hợp pháp với bên thứ ba nhưng sẽ bí mật giữ bộ nhớ chính của quý khách với tiền xu an toàn", - help2: "Bộ lưu trữ mới sẽ có đầy đủ chức năng và quý khách có thể lưu trữ một số lượng tối thiểu ở đó với thông tin đáng tin cậy hơn", + help: + "Trong một số trường hợp nhất định, quý khách có thể bắt buộc phải tiết lộ mật khẩu. Để giữ tiền xu của quý khách được an toàn, Veles Wallet có thể tạo một bộ lưu trữ được mã hóa khác, với một mật khẩu khác. Dưới áp lực, quý khách có thể tiết lộ mật khẩu này cho bên thứ ba. Nếu được nhập vào Veles Wallet, nó sẽ mở khóa bộ nhớ giả mới. Điều này có vẻ hợp pháp với bên thứ ba nhưng sẽ bí mật giữ bộ nhớ chính của quý khách với tiền xu an toàn", + help2: + "Bộ lưu trữ mới sẽ có đầy đủ chức năng và quý khách có thể lưu trữ một số lượng tối thiểu ở đó với thông tin đáng tin cậy hơn", create_fake_storage: "Tạo lưu trữ được mã hóa giả", go_back: "Quay lại", create_password: "Tạo mật khẩu", - create_password_explanation: "Mật khẩu cho bộ nhớ giả không được khớp với mật khẩu cho bộ lưu trữ chính của quý khách", - password_should_not_match: "Mật khẩu cho bộ nhớ giả không được khớp với mật khẩu cho bộ lưu trữ chính của quý khách", + create_password_explanation: + "Mật khẩu cho bộ nhớ giả không được khớp với mật khẩu cho bộ lưu trữ chính của quý khách", + password_should_not_match: + "Mật khẩu cho bộ nhớ giả không được khớp với mật khẩu cho bộ lưu trữ chính của quý khách", retype_password: "Nhập lại mật khẩu", passwords_do_not_match: "Mật khẩu không khớp, vui lòng thử lại", - success: "Thành công", + success: "Thành công" }, lnd: { title: "quản lý tiền", @@ -210,12 +228,14 @@ module.exports = { withdraw: "Rút tiền", placeholder: "Hóa đơn", expired: "Hết hạn", - sameWalletAsInvoiceError: "Quý khách không thể thanh toán hóa đơn với cùng một ví được sử dụng để tạo hóa đơn", + sameWalletAsInvoiceError: + "Quý khách không thể thanh toán hóa đơn với cùng một ví được sử dụng để tạo hóa đơn" }, pleasebackup: { title: "Ví của quý khách đã được tạo...", - text: "Vui lòng dành chút thời gian để viết cụm ghi nhớ này trên một tờ giấy. Nó sẽ là bản sao lưu của quý khách, quý khách có thể sử dụng nó để khôi phục ví ở trên thiết bị khác", - ok: "OK, tôi đã viết nó!", + text: + "Vui lòng dành chút thời gian để viết cụm ghi nhớ này trên một tờ giấy. Nó sẽ là bản sao lưu của quý khách, quý khách có thể sử dụng nó để khôi phục ví ở trên thiết bị khác", + ok: "OK, tôi đã viết nó!" }, lndViewInvoice: { wasnt_paid_and_expired: "Hóa đơn này không được thanh toán và đã hết hạn", @@ -224,6 +244,6 @@ module.exports = { sats: "sats", for: "Cho", additional_info: "Thông tin thêm", - open_direct_channel: "Mở kênh trực tiếp với nút này", - }, + open_direct_channel: "Mở kênh trực tiếp với nút này" + } }; diff --git a/loc/zh_cn.js b/loc/zh_cn.js index 9039ff9bc3f..23b0bf2bc5b 100755 --- a/loc/zh_cn.js +++ b/loc/zh_cn.js @@ -5,12 +5,13 @@ module.exports = { bad_password: "密码无效,请重试", never: "不", continue: "继续", - ok: "好的", + ok: "好的" }, wallets: { select_wallet: "选择钱包", options: "选项", - createBitcoinWallet: "您当前没有bitcoin钱包,为了支持闪电钱包,我们需要创建或者导入一个比特币钱包,是否需要继续?", + createBitcoinWallet: + "您当前没有bitcoin钱包,为了支持闪电钱包,我们需要创建或者导入一个比特币钱包,是否需要继续?", list: { app_name: "Veles Wallet", title: "钱包", @@ -24,14 +25,15 @@ module.exports = { empty_txs2: "当前无信息", empty_txs1_lightning: "闪电钱包可以进行日常交易。 费用极低,速度飞快。", empty_txs2_lightning: "要开始使用它,请点击“管理资金”并充值。", - tap_here_to_buy: "点击购买比特币", + tap_here_to_buy: "点击购买比特币" }, reorder: { - title: "重新排列钱包", + title: "重新排列钱包" }, add: { title: "添加钱包", - description: "你可以扫描你的纸质备份钱包 (WIF格式),或者创建一个新钱包。默认支持隔离见证钱包。", + description: + "你可以扫描你的纸质备份钱包 (WIF格式),或者创建一个新钱包。默认支持隔离见证钱包。", scan: "扫描", create: "创建", label_new_segwit: "新隔离见证(Segwit)", @@ -43,7 +45,7 @@ module.exports = { imported: "已经导入", coming_soon: "即将来临", lightning: "闪电", - bitcoin: "Veles", + bitcoin: "Veles" }, details: { title: "钱包", @@ -60,23 +62,24 @@ module.exports = { delete_this_wallet: "删除这个钱包", export_backup: "导出 / 备份", buy_bitcoin: "购买比特币", - show_xpub: "展示钱包 XPUB", + show_xpub: "展示钱包 XPUB" }, export: { - title: "钱包导出", + title: "钱包导出" }, xpub: { title: "钱包 XPUB", - copiedToClipboard: "复制到粘贴板.", + copiedToClipboard: "复制到粘贴板." }, import: { title: "导入", - explanation: "输入你的助记词,私钥,WIF,或者其他格式的数据。Veles Wallet将尽可能地自动识别格式并导入钱包。", + explanation: + "输入你的助记词,私钥,WIF,或者其他格式的数据。Veles Wallet将尽可能地自动识别格式并导入钱包。", imported: "已经导入", error: "导入失败,请确认你提供的信息是有效的", success: "成功", do_import: "导入", - scan_qr: "或扫描二维码替代?", + scan_qr: "或扫描二维码替代?" }, scanQrWif: { go_back: "回退", @@ -91,15 +94,15 @@ module.exports = { with_address: "地址为", imported_segwit: "SegWit已经导入", imported_legacy: "Legacy已经导入", - imported_watchonly: "导入只读", - }, + imported_watchonly: "导入只读" + } }, transactions: { list: { tabBarLabel: "转账", title: "转账", description: "当前所有钱包的转入和转出记录", - conf: "确认", + conf: "确认" }, details: { title: "转账", @@ -107,13 +110,13 @@ module.exports = { to: "输出", copy: "复制", transaction_details: "转账详情", - show_in_block_explorer: "在区块探测中查看", - }, + show_in_block_explorer: "在区块探测中查看" + } }, send: { header: "发送", success: { - done: "完成", + done: "完成" }, details: { title: "创建交易", @@ -130,11 +133,11 @@ module.exports = { send: "发送", create: "创建", remaining_balance: "剩余金额", - total_exceeds_balance: "余额不足", + total_exceeds_balance: "余额不足" }, confirm: { header: "确认", - sendNow: "现在发送", + sendNow: "现在发送" }, create: { details: "详情", @@ -149,8 +152,8 @@ module.exports = { satoshi_per_byte: "聪每字节", memo: "备忘录", broadcast: "广播", - not_enough_fee: "手续费不够,请增加手续费", - }, + not_enough_fee: "手续费不够,请增加手续费" + } }, receive: { header: "收款", @@ -160,14 +163,14 @@ module.exports = { copiedToClipboard: "复制到粘贴板。", label: "描述", create: "创建", - setAmount: "收款金额", + setAmount: "收款金额" }, - scan_lnurl: "扫描收款", + scan_lnurl: "扫描收款" }, buyBitcoin: { header: "购买比特币", tap_your_address: "点击地址复制到粘贴板", - copied: "复制到粘贴板!", + copied: "复制到粘贴板!" }, settings: { header: "设置", @@ -187,11 +190,12 @@ module.exports = { language: "语言", currency: "货币", advanced_options: "高级选项", - enable_advanced_mode: "启用高级模式", + enable_advanced_mode: "启用高级模式" }, plausibledeniability: { title: "可否认性", - help: "在某些情况下,您可能被迫透露密码。 为了确保您的比特币安全,Veles Wallet可以创建另一个具有不同密码的加密存储。 在被胁迫情况下下,您可以将此密码透露给第三者。 如果在Veles Wallet中输入,它将解锁新的虚拟存储。 这对于第三方来说似乎合法,但是会秘密地将您的比特币存放在安全的地方。", + help: + "在某些情况下,您可能被迫透露密码。 为了确保您的比特币安全,Veles Wallet可以创建另一个具有不同密码的加密存储。 在被胁迫情况下下,您可以将此密码透露给第三者。 如果在Veles Wallet中输入,它将解锁新的虚拟存储。 这对于第三方来说似乎合法,但是会秘密地将您的比特币存放在安全的地方。", help2: "新的空间具备完整的功能,你可以存少量的金额在里面。", create_fake_storage: "创建虚拟加密存储", go_back: "回退", @@ -200,7 +204,7 @@ module.exports = { password_should_not_match: "虚拟存储空间密码不能和主存储空间密码相同", retype_password: "重输密码", passwords_do_not_match: "两次输入密码不同,请重新输入", - success: "成功", + success: "成功" }, lnd: { title: "管理资金", @@ -210,12 +214,13 @@ module.exports = { withdraw: "提取", placeholder: "账单", expired: "失效", - sameWalletAsInvoiceError: "你不能用创建账单的钱包去支付", + sameWalletAsInvoiceError: "你不能用创建账单的钱包去支付" }, pleasebackup: { title: "您的钱包已创建...", - text: "请花一点时间在纸上写下这个助记词。 这是您的备份,可用于在其他设备上还原钱包。", - ok: "好吧,我写下来!", + text: + "请花一点时间在纸上写下这个助记词。 这是您的备份,可用于在其他设备上还原钱包。", + ok: "好吧,我写下来!" }, lndViewInvoice: { wasnt_paid_and_expired: "该账单未付款且已过期", @@ -224,6 +229,6 @@ module.exports = { sats: "sats", for: "对于", additional_info: "附加信息", - open_direct_channel: "使用此节点打开直通道", - }, + open_direct_channel: "使用此节点打开直通道" + } }; diff --git a/loc/zh_tw.js b/loc/zh_tw.js index 87554524f2d..1a7570b84df 100644 --- a/loc/zh_tw.js +++ b/loc/zh_tw.js @@ -1,235 +1,241 @@ module.exports = { _: { - storage_is_encrypted: '你的資訊已經被加密, 請輸入密碼解密', - enter_password: '輸入密碼', - bad_password: '密碼無效,請重試', - never: '不', - continue: '繼續', - ok: '好的', + storage_is_encrypted: "你的資訊已經被加密, 請輸入密碼解密", + enter_password: "輸入密碼", + bad_password: "密碼無效,請重試", + never: "不", + continue: "繼續", + ok: "好的" }, wallets: { - select_wallet: '選擇錢包', - options: '選項', - createBitcoinWallet: '您當前沒有bitcoin錢包. 為了支援閃電錢包, 我們需要建立或者匯入一個比特幣錢包. 是否需要繼續?', + select_wallet: "選擇錢包", + options: "選項", + createBitcoinWallet: + "您當前沒有bitcoin錢包. 為了支援閃電錢包, 我們需要建立或者匯入一個比特幣錢包. 是否需要繼續?", list: { - app_name: 'Veles Wallet', - title: '錢包', - header: '一個錢包代表一對的私鑰和地址' + '你可以通過分享收款.', - add: '新增錢包', - create_a_wallet: '建立一個錢包', - create_a_wallet1: '建立錢包是免費的,你可以', - create_a_wallet2: '想建立多少就建立多少個', - latest_transaction: '最近的轉賬', - empty_txs1: '你的轉賬資訊將展示在這裡', - empty_txs2: '當前無資訊', + app_name: "Veles Wallet", + title: "錢包", + header: "一個錢包代表一對的私鑰和地址" + "你可以通過分享收款.", + add: "新增錢包", + create_a_wallet: "建立一個錢包", + create_a_wallet1: "建立錢包是免費的,你可以", + create_a_wallet2: "想建立多少就建立多少個", + latest_transaction: "最近的轉賬", + empty_txs1: "你的轉賬資訊將展示在這裡", + empty_txs2: "當前無資訊", empty_txs1_lightning: - 'Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.', - empty_txs2_lightning: '\nTo start using it tap on "manage funds" and topup your balance.', - tap_here_to_buy: '點選購買比特幣', + "Lightning wallet should be used for your daily transactions. Fees are unfairly cheap and speed is blazing fast.", + empty_txs2_lightning: + '\nTo start using it tap on "manage funds" and topup your balance.', + tap_here_to_buy: "點選購買比特幣" }, reorder: { - title: '重新排列錢包', + title: "重新排列錢包" }, add: { - title: '新增錢包', - description: '你可以掃描你的紙質備份錢包 (WIF格式), 或者建立一個新錢包. 預設支援隔離見證錢包', - scan: '掃描', - create: '建立', - label_new_segwit: '新隔離見證(Segwit)', - label_new_lightning: '新閃電', - wallet_name: '錢包名稱', - wallet_type: '類型', - or: '或', - import_wallet: '匯入錢包', - imported: '已經匯入', - coming_soon: '即將來臨', - lightning: '閃電', - bitcoin: '比特幣', + title: "新增錢包", + description: + "你可以掃描你的紙質備份錢包 (WIF格式), 或者建立一個新錢包. 預設支援隔離見證錢包", + scan: "掃描", + create: "建立", + label_new_segwit: "新隔離見證(Segwit)", + label_new_lightning: "新閃電", + wallet_name: "錢包名稱", + wallet_type: "類型", + or: "或", + import_wallet: "匯入錢包", + imported: "已經匯入", + coming_soon: "即將來臨", + lightning: "閃電", + bitcoin: "比特幣" }, details: { - title: '錢包', - address: '地址', - type: '類型', - label: '標籤', - destination: '目的', - description: '描述', - are_you_sure: '你確認麼?', - yes_delete: '是的,刪除', - no_cancel: '不,取消', - delete: '刪除', - save: '儲存', - delete_this_wallet: '刪除這個錢包', - export_backup: '匯出備份', - buy_bitcoin: '購買比特幣', - show_xpub: '展示錢包 XPUB', + title: "錢包", + address: "地址", + type: "類型", + label: "標籤", + destination: "目的", + description: "描述", + are_you_sure: "你確認麼?", + yes_delete: "是的,刪除", + no_cancel: "不,取消", + delete: "刪除", + save: "儲存", + delete_this_wallet: "刪除這個錢包", + export_backup: "匯出備份", + buy_bitcoin: "購買比特幣", + show_xpub: "展示錢包 XPUB" }, export: { - title: '錢包匯出', + title: "錢包匯出" }, xpub: { - title: '錢包 XPUB', - copiedToClipboard: '複製到貼上板.', + title: "錢包 XPUB", + copiedToClipboard: "複製到貼上板." }, import: { - title: '匯入', - explanation: '輸入你的助記詞,私鑰或者WIF, 或者其他格式的資料. Veles Wallet將盡可能的自動識別資料格式並匯入錢包', - imported: '已經匯入', - error: '匯入失敗,請確認你提供的資訊是有效的', - success: '成功', - do_import: '匯入', - scan_qr: '或掃面二維碼', + title: "匯入", + explanation: + "輸入你的助記詞,私鑰或者WIF, 或者其他格式的資料. Veles Wallet將盡可能的自動識別資料格式並匯入錢包", + imported: "已經匯入", + error: "匯入失敗,請確認你提供的資訊是有效的", + success: "成功", + do_import: "匯入", + scan_qr: "或掃面二維碼" }, scanQrWif: { - go_back: '回退', - cancel: '取消', - decoding: '解碼中', - input_password: '輸入密碼', - password_explain: '這是一個BIP38加密的私鑰', - bad_password: '密碼錯誤', - wallet_already_exists: '當前錢包已經存在', - bad_wif: 'WIF格式無效', - imported_wif: 'WIF已經匯入', - with_address: ' 地址為', - imported_segwit: 'SegWit已經匯入', - imported_legacy: 'Legacy已經匯入', - imported_watchonly: '匯入只讀', - }, + go_back: "回退", + cancel: "取消", + decoding: "解碼中", + input_password: "輸入密碼", + password_explain: "這是一個BIP38加密的私鑰", + bad_password: "密碼錯誤", + wallet_already_exists: "當前錢包已經存在", + bad_wif: "WIF格式無效", + imported_wif: "WIF已經匯入", + with_address: " 地址為", + imported_segwit: "SegWit已經匯入", + imported_legacy: "Legacy已經匯入", + imported_watchonly: "匯入只讀" + } }, transactions: { list: { - tabBarLabel: '轉賬', - title: '轉賬', - description: '當前所有錢包的轉入和轉出記錄', - conf: '配置', + tabBarLabel: "轉賬", + title: "轉賬", + description: "當前所有錢包的轉入和轉出記錄", + conf: "配置" }, details: { - title: '轉賬', - from: '輸入', - to: '輸出', - copy: '複製', - transaction_details: '轉賬詳情', - show_in_block_explorer: '區塊瀏覽器展示', - }, + title: "轉賬", + from: "輸入", + to: "輸出", + copy: "複製", + transaction_details: "轉賬詳情", + show_in_block_explorer: "區塊瀏覽器展示" + } }, send: { - header: '傳送', + header: "傳送", details: { - title: '建立交易', - amount_field_is_not_valid: '金額格式無效', - fee_field_is_not_valid: '費用格式無效', - address_field_is_not_valid: '地址內容無效', - total_exceeds_balance: '餘額不足', - create_tx_error: '建立交易失敗. 請確認地址格式正確.', - address: '地址', - amount_placeholder: '傳送金額(in VLS)', - fee_placeholder: '手續費用 (in VLS)', - note_placeholder: '訊息', - cancel: '取消', - scan: '掃描', - send: '傳送', - create: '建立', - remaining_balance: '剩餘金額', + title: "建立交易", + amount_field_is_not_valid: "金額格式無效", + fee_field_is_not_valid: "費用格式無效", + address_field_is_not_valid: "地址內容無效", + total_exceeds_balance: "餘額不足", + create_tx_error: "建立交易失敗. 請確認地址格式正確.", + address: "地址", + amount_placeholder: "傳送金額(in VLS)", + fee_placeholder: "手續費用 (in VLS)", + note_placeholder: "訊息", + cancel: "取消", + scan: "掃描", + send: "傳送", + create: "建立", + remaining_balance: "剩餘金額" }, confirm: { - header: '確認', - sendNow: '現在傳送', + header: "確認", + sendNow: "現在傳送" }, success: { - done: '完成', + done: "完成" }, create: { - details: '詳情', - title: '建立詳情', - error: '建立交易失敗. 無效地址或金額?', - go_back: '回退', - this_is_hex: '這個是交易的十六進位制資料, 簽名並廣播到全網路.', - to: '到', - amount: '金額', - fee: '手續費', - tx_size: '交易大小', - satoshi_per_byte: '蔥每byte', - memo: '訊息', - broadcast: '廣播', - not_enough_fee: '手續費不夠,請增加手續費', - }, + details: "詳情", + title: "建立詳情", + error: "建立交易失敗. 無效地址或金額?", + go_back: "回退", + this_is_hex: "這個是交易的十六進位制資料, 簽名並廣播到全網路.", + to: "到", + amount: "金額", + fee: "手續費", + tx_size: "交易大小", + satoshi_per_byte: "蔥每byte", + memo: "訊息", + broadcast: "廣播", + not_enough_fee: "手續費不夠,請增加手續費" + } }, receive: { - header: '收款', + header: "收款", details: { - title: '分享這個地址給付款人', - share: '分享', - copiedToClipboard: '複製到貼上板.', - label: '描述', - create: '建立', - setAmount: '收款金額', - }, + title: "分享這個地址給付款人", + share: "分享", + copiedToClipboard: "複製到貼上板.", + label: "描述", + create: "建立", + setAmount: "收款金額" + } }, buyBitcoin: { - header: '購買比特幣', - tap_your_address: '點選地址複製到貼上板:', - copied: '複製到貼上板!', + header: "購買比特幣", + tap_your_address: "點選地址複製到貼上板:", + copied: "複製到貼上板!" }, settings: { - header: '設定', - plausible_deniability: '可否認性...', - storage_not_encrypted: '儲存:未加密', - storage_encrypted: '儲存:加密中', - password: '密碼', - password_explain: '建立你的加密密碼', - retype_password: '再次輸入密碼', - passwords_do_not_match: '兩次輸入密碼不同', - encrypt_storage: '加密儲存', - lightning_settings: '閃電網路設定', - lightning_settings_explain: '如要要連線你自己的閃電節點請安裝LndHub' + ' 並把url地址輸入到下面. 空白將使用預設的LndHub (lndhub.io)', - save: '儲存', - about: '關於', - language: '語言', - currency: '貨幣', - advanced_options: 'Advanced Options', - enable_advanced_mode: 'Enable advanced mode', + header: "設定", + plausible_deniability: "可否認性...", + storage_not_encrypted: "儲存:未加密", + storage_encrypted: "儲存:加密中", + password: "密碼", + password_explain: "建立你的加密密碼", + retype_password: "再次輸入密碼", + passwords_do_not_match: "兩次輸入密碼不同", + encrypt_storage: "加密儲存", + lightning_settings: "閃電網路設定", + lightning_settings_explain: + "如要要連線你自己的閃電節點請安裝LndHub" + + " 並把url地址輸入到下面. 空白將使用預設的LndHub (lndhub.io)", + save: "儲存", + about: "關於", + language: "語言", + currency: "貨幣", + advanced_options: "Advanced Options", + enable_advanced_mode: "Enable advanced mode" }, plausibledeniability: { - title: '可否認性', + title: "可否認性", help: - '在某些情況下, 你不得不暴露 ' + - '密碼. 為了讓你的比特幣更加安全, Veles Wallet可以建立一些 ' + - '加密空間, 用不同的密碼. 在壓力之下, ' + - '你可以暴露這個錢包密碼. 再次進入 ' + - 'Veles Wallet, 我們會解鎖一些虛擬空間. 對第三方來說看上去' + - '是合理的, 但會偷偷的幫你保證主錢包的安全 ' + - '幣也就安全了.', - help2: '新的空間具備完整的功能,你可以存在 ' + '少量的金額在裡面.', - create_fake_storage: '建立虛擬加密儲存', - go_back: '回退', - create_password: '建立密碼', - create_password_explanation: '虛擬儲存空間密碼不能和主儲存空間密碼相同', - password_should_not_match: '虛擬儲存空間密碼不能和主儲存空間密碼相同', - retype_password: '重輸密碼', - passwords_do_not_match: '兩次輸入密碼不同,請重新輸入', - success: '成功', + "在某些情況下, 你不得不暴露 " + + "密碼. 為了讓你的比特幣更加安全, Veles Wallet可以建立一些 " + + "加密空間, 用不同的密碼. 在壓力之下, " + + "你可以暴露這個錢包密碼. 再次進入 " + + "Veles Wallet, 我們會解鎖一些虛擬空間. 對第三方來說看上去" + + "是合理的, 但會偷偷的幫你保證主錢包的安全 " + + "幣也就安全了.", + help2: "新的空間具備完整的功能,你可以存在 " + "少量的金額在裡面.", + create_fake_storage: "建立虛擬加密儲存", + go_back: "回退", + create_password: "建立密碼", + create_password_explanation: "虛擬儲存空間密碼不能和主儲存空間密碼相同", + password_should_not_match: "虛擬儲存空間密碼不能和主儲存空間密碼相同", + retype_password: "重輸密碼", + passwords_do_not_match: "兩次輸入密碼不同,請重新輸入", + success: "成功" }, lnd: { - title: '配置資金支援', - choose_source_wallet: '選擇一個資金源錢包', - refill_lnd_balance: '給閃電錢包充值', - refill: '充值', - withdraw: '提取', - expired: '超時', - sameWalletAsInvoiceError: '你不能用建立賬單的錢包去支付該賬單', + title: "配置資金支援", + choose_source_wallet: "選擇一個資金源錢包", + refill_lnd_balance: "給閃電錢包充值", + refill: "充值", + withdraw: "提取", + expired: "超時", + sameWalletAsInvoiceError: "你不能用建立賬單的錢包去支付該賬單" }, pleasebackup: { - title: 'Your wallet is created...', + title: "Your wallet is created...", text: "Please take a moment to write down this mnemonic phrase on a piece of paper. It's your backup you can use to restore the wallet on other device.", - ok: 'OK, I wrote this down!', + ok: "OK, I wrote this down!" }, lndViewInvoice: { - wasnt_paid_and_expired: 'This invoice was not paid for and has expired', - has_been_paid: 'This invoice has been paid for', - please_pay: 'Please pay', - sats: 'sats', - for: 'For:', - additional_info: 'Additional Information', - open_direct_channel: 'Open direct channel with this node:', - }, + wasnt_paid_and_expired: "This invoice was not paid for and has expired", + has_been_paid: "This invoice has been paid for", + please_pay: "Please pay", + sats: "sats", + for: "For:", + additional_info: "Additional Information", + open_direct_channel: "Open direct channel with this node:" + } }; diff --git a/models/bitcoinTransactionInfo.js b/models/bitcoinTransactionInfo.js index f5daf18e0c6..ab47b10a04b 100644 --- a/models/bitcoinTransactionInfo.js +++ b/models/bitcoinTransactionInfo.js @@ -1,5 +1,5 @@ export class BitcoinTransaction { - constructor(address = '', amount) { + constructor(address = "", amount) { this.address = address; this.amount = amount; } diff --git a/models/bitcoinUnits.js b/models/bitcoinUnits.js index 4c43e56227b..912b04d5ddf 100644 --- a/models/bitcoinUnits.js +++ b/models/bitcoinUnits.js @@ -1,11 +1,11 @@ export const BitcoinUnit = Object.freeze({ - BTC: 'VLS', - SATS: 'vlsats', - LOCAL_CURRENCY: 'local_currency', - MAX: 'MAX', + BTC: "VLS", + SATS: "vlsats", + LOCAL_CURRENCY: "local_currency", + MAX: "MAX" }); export const Chain = Object.freeze({ - ONCHAIN: 'ONCHAIN', - OFFCHAIN: 'OFFCHAIN', + ONCHAIN: "ONCHAIN", + OFFCHAIN: "OFFCHAIN" }); diff --git a/models/fiatUnit.js b/models/fiatUnit.js index 6e432dcda6c..102d6835285 100644 --- a/models/fiatUnit.js +++ b/models/fiatUnit.js @@ -1,27 +1,27 @@ export const FiatUnit = Object.freeze({ - USD: { endPointKey: 'USD', symbol: '$', locale: 'en-US' }, - AUD: { endPointKey: 'AUD', symbol: '$', locale: 'en-AU' }, - BRL: { endPointKey: 'BRL', symbol: 'R$', locale: 'pt-BR' }, - CAD: { endPointKey: 'CAD', symbol: '$', locale: 'en-CA' }, - CHF: { endPointKey: 'CHF', symbol: 'CHF', locale: 'de-CH' }, - CZK: { endPointKey: 'CZK', symbol: 'Kč', locale: 'cs-CZ' }, - CNY: { endPointKey: 'CNY', symbol: '¥', locale: 'zh-CN' }, - EUR: { endPointKey: 'EUR', symbol: '€', locale: 'en-EN' }, - GBP: { endPointKey: 'GBP', symbol: '£', locale: 'en-GB' }, - HRK: { endPointKey: 'HRK', symbol: 'HRK', locale: 'hr-HR' }, - HUF: { endPointKey: 'HUF', symbol: 'Ft', locale: 'hu-HU' }, - INR: { endPointKey: 'INR', symbol: '₹', locale: 'hi-HN' }, - JPY: { endPointKey: 'JPY', symbol: '¥', locale: 'ja-JP' }, - KRW: { endPointKey: 'KRW', symbol: '₩', locale: 'ko-KR' }, - MXN: { endPointKey: 'MXN', symbol: '$', locale: 'es-MX' }, - MYR: { endPointKey: 'MYR', symbol: 'RM', locale: 'ms-MY' }, - NOK: { endPointKey: 'NOK', symbol: 'kr', locale: 'nb-NO' }, - NZD: { endPointKey: 'NZD', symbol: '$', locale: 'en-NZ' }, - PLN: { endPointKey: 'PLN', symbol: 'zł', locale: 'pl-PL' }, - RUB: { endPointKey: 'RUB', symbol: '₽', locale: 'ru-RU' }, - SGD: { endPointKey: 'SGD', symbol: 'S$', locale: 'zh-SG' }, - SEK: { endPointKey: 'SEK', symbol: 'kr', locale: 'sv-SE' }, - THB: { endPointKey: 'THB', symbol: '฿', locale: 'th-TH' }, - VEF: { endPointKey: 'VEF', symbol: 'Bs.', locale: 'es-VE' }, - ZAR: { endPointKey: 'ZAR', symbol: 'R', locale: 'en-ZA' }, + USD: { endPointKey: "USD", symbol: "$", locale: "en-US" }, + AUD: { endPointKey: "AUD", symbol: "$", locale: "en-AU" }, + BRL: { endPointKey: "BRL", symbol: "R$", locale: "pt-BR" }, + CAD: { endPointKey: "CAD", symbol: "$", locale: "en-CA" }, + CHF: { endPointKey: "CHF", symbol: "CHF", locale: "de-CH" }, + CZK: { endPointKey: "CZK", symbol: "Kč", locale: "cs-CZ" }, + CNY: { endPointKey: "CNY", symbol: "¥", locale: "zh-CN" }, + EUR: { endPointKey: "EUR", symbol: "€", locale: "en-EN" }, + GBP: { endPointKey: "GBP", symbol: "£", locale: "en-GB" }, + HRK: { endPointKey: "HRK", symbol: "HRK", locale: "hr-HR" }, + HUF: { endPointKey: "HUF", symbol: "Ft", locale: "hu-HU" }, + INR: { endPointKey: "INR", symbol: "₹", locale: "hi-HN" }, + JPY: { endPointKey: "JPY", symbol: "¥", locale: "ja-JP" }, + KRW: { endPointKey: "KRW", symbol: "₩", locale: "ko-KR" }, + MXN: { endPointKey: "MXN", symbol: "$", locale: "es-MX" }, + MYR: { endPointKey: "MYR", symbol: "RM", locale: "ms-MY" }, + NOK: { endPointKey: "NOK", symbol: "kr", locale: "nb-NO" }, + NZD: { endPointKey: "NZD", symbol: "$", locale: "en-NZ" }, + PLN: { endPointKey: "PLN", symbol: "zł", locale: "pl-PL" }, + RUB: { endPointKey: "RUB", symbol: "₽", locale: "ru-RU" }, + SGD: { endPointKey: "SGD", symbol: "S$", locale: "zh-SG" }, + SEK: { endPointKey: "SEK", symbol: "kr", locale: "sv-SE" }, + THB: { endPointKey: "THB", symbol: "฿", locale: "th-TH" }, + VEF: { endPointKey: "VEF", symbol: "Bs.", locale: "es-VE" }, + ZAR: { endPointKey: "ZAR", symbol: "R", locale: "en-ZA" } }); diff --git a/models/networkTransactionFees.js b/models/networkTransactionFees.js index 70e842287af..ee641d4f5de 100644 --- a/models/networkTransactionFees.js +++ b/models/networkTransactionFees.js @@ -1,18 +1,19 @@ -import { BitcoinUnit } from './bitcoinUnits'; -import BigNumber from 'bignumber.js'; -let loc = require('../loc'); +import { BitcoinUnit } from "./bitcoinUnits"; +import BigNumber from "bignumber.js"; -const BlueElectrum = require('../BlueElectrum'); +const loc = require("../loc"); + +const BlueElectrum = require("../BlueElectrum"); export const NetworkTransactionFeeType = Object.freeze({ - FAST: 'Fast', - MEDIUM: 'MEDIUM', - SLOW: 'SLOW', - CUSTOM: 'CUSTOM', + FAST: "Fast", + MEDIUM: "MEDIUM", + SLOW: "SLOW", + CUSTOM: "CUSTOM" }); export class NetworkTransactionFee { - static StorageKey = 'NetworkTransactionFee'; + static StorageKey = "NetworkTransactionFee"; constructor(fastestFee = 1, halfHourFee = 1, hourFee = 1) { this.fastestFee = fastestFee; @@ -25,28 +26,28 @@ export default class NetworkTransactionFees { static recommendedFees() { return new Promise(async (resolve, reject) => { try { - let response = await BlueElectrum.estimateFees(); - if (typeof response === 'object') { + const response = await BlueElectrum.estimateFees(); + if (typeof response === "object") { const fast = loc.formatBalanceWithoutSuffix( new BigNumber(response.fast) .multipliedBy(1) .toNumber() .toFixed(0), - BitcoinUnit.SATS, + BitcoinUnit.SATS ); const medium = loc.formatBalanceWithoutSuffix( new BigNumber(response.medium) .multipliedBy(1) .toNumber() .toFixed(0), - BitcoinUnit.SATS, + BitcoinUnit.SATS ); const slow = loc.formatBalanceWithoutSuffix( new BigNumber(response.slow) .multipliedBy(1) .toNumber() .toFixed(0), - BitcoinUnit.SATS, + BitcoinUnit.SATS ); const networkFee = new NetworkTransactionFee(fast, medium, slow); resolve(networkFee); diff --git a/models/signer.js b/models/signer.js index fbd766f29cd..c5aa829a959 100644 --- a/models/signer.js +++ b/models/signer.js @@ -6,18 +6,27 @@ * https://github.com/Overtorment/Cashier-BTC * **/ -const bitcoinjs = require('bitcoinjs-lib'); +const bitcoinjs = require("bitcoinjs-lib"); + const _p2wpkh = bitcoinjs.payments.p2wpkh; const _p2sh = bitcoinjs.payments.p2sh; const toSatoshi = num => parseInt((num * 100000000).toFixed(0)); -exports.createHDTransaction = function(utxos, toAddress, amount, fixedFee, changeAddress) { - let feeInSatoshis = parseInt((fixedFee * 100000000).toFixed(0)); - let amountToOutputSatoshi = parseInt(((amount - fixedFee) * 100000000).toFixed(0)); // how much payee should get - let txb = new bitcoinjs.TransactionBuilder(); +exports.createHDTransaction = function( + utxos, + toAddress, + amount, + fixedFee, + changeAddress +) { + const feeInSatoshis = parseInt((fixedFee * 100000000).toFixed(0)); + const amountToOutputSatoshi = parseInt( + ((amount - fixedFee) * 100000000).toFixed(0) + ); // how much payee should get + const txb = new bitcoinjs.TransactionBuilder(); txb.setVersion(1); let unspentAmountSatoshi = 0; - let ourOutputs = {}; + const ourOutputs = {}; let outputNum = 0; for (const unspent of utxos) { if (unspent.confirmations < 1) { @@ -35,7 +44,9 @@ exports.createHDTransaction = function(utxos, toAddress, amount, fixedFee, chang outputNum++; } if (unspentAmountSatoshi < amountToOutputSatoshi + feeInSatoshis) { - throw new Error('Not enough balance. Please, try sending a smaller amount.'); + throw new Error( + "Not enough balance. Please, try sending a smaller amount." + ); } // adding outputs @@ -43,10 +54,16 @@ exports.createHDTransaction = function(utxos, toAddress, amount, fixedFee, chang txb.addOutput(toAddress, amountToOutputSatoshi); if (amountToOutputSatoshi + feeInSatoshis < unspentAmountSatoshi) { // sending less than we have, so the rest should go back - if (unspentAmountSatoshi - amountToOutputSatoshi - feeInSatoshis > 3 * feeInSatoshis) { + if ( + unspentAmountSatoshi - amountToOutputSatoshi - feeInSatoshis > + 3 * feeInSatoshis + ) { // to prevent @dust error change transferred amount should be at least 3xfee. // if not - we just dont send change and it wil add to fee - txb.addOutput(changeAddress, unspentAmountSatoshi - amountToOutputSatoshi - feeInSatoshis); + txb.addOutput( + changeAddress, + unspentAmountSatoshi - amountToOutputSatoshi - feeInSatoshis + ); } } @@ -54,44 +71,52 @@ exports.createHDTransaction = function(utxos, toAddress, amount, fixedFee, chang for (let c = 0; c <= outputNum; c++) { txb.sign({ - prevOutScriptType: 'p2pkh', + prevOutScriptType: "p2pkh", vin: c, - keyPair: ourOutputs[c].keyPair, + keyPair: ourOutputs[c].keyPair }); } - let tx = txb.build(); + const tx = txb.build(); return tx.toHex(); }; -exports.createHDSegwitTransaction = function(utxos, toAddress, amount, fixedFee, changeAddress) { - let feeInSatoshis = parseInt((fixedFee * 100000000).toFixed(0)); - let amountToOutputSatoshi = parseInt(((amount - fixedFee) * 100000000).toFixed(0)); // how much payee should get - let psbt = new bitcoinjs.Psbt(); +exports.createHDSegwitTransaction = function( + utxos, + toAddress, + amount, + fixedFee, + changeAddress +) { + const feeInSatoshis = parseInt((fixedFee * 100000000).toFixed(0)); + const amountToOutputSatoshi = parseInt( + ((amount - fixedFee) * 100000000).toFixed(0) + ); // how much payee should get + const psbt = new bitcoinjs.Psbt(); psbt.setVersion(1); let unspentAmountSatoshi = 0; - let ourOutputs = []; + const ourOutputs = []; let outputNum = 0; for (const unspent of utxos) { if (unspent.confirmations < 1) { // using only confirmed outputs continue; } - let keyPair = bitcoinjs.ECPair.fromWIF(unspent.wif); - let p2wpkh = _p2wpkh({ - pubkey: keyPair.publicKey, + const keyPair = bitcoinjs.ECPair.fromWIF(unspent.wif); + const p2wpkh = _p2wpkh({ + pubkey: keyPair.publicKey }); - let p2sh = _p2sh({ - redeem: p2wpkh, + const p2sh = _p2sh({ + redeem: p2wpkh }); psbt.addInput({ hash: unspent.txid, index: unspent.vout, witnessUtxo: { script: p2sh.output, - value: unspent.value, + value: unspent.value }, - redeemScript: p2wpkh.output, + redeemScript: p2wpkh.output }); ourOutputs[outputNum] = ourOutputs[outputNum] || {}; ourOutputs[outputNum].keyPair = keyPair; @@ -106,23 +131,28 @@ exports.createHDSegwitTransaction = function(utxos, toAddress, amount, fixedFee, } if (unspentAmountSatoshi < amountToOutputSatoshi + feeInSatoshis) { - throw new Error('Not enough balance. Please, try sending a smaller amount.'); + throw new Error( + "Not enough balance. Please, try sending a smaller amount." + ); } // adding outputs psbt.addOutput({ address: toAddress, - value: amountToOutputSatoshi, + value: amountToOutputSatoshi }); if (amountToOutputSatoshi + feeInSatoshis < unspentAmountSatoshi) { // sending less than we have, so the rest should go back - if (unspentAmountSatoshi - amountToOutputSatoshi - feeInSatoshis > 3 * feeInSatoshis) { + if ( + unspentAmountSatoshi - amountToOutputSatoshi - feeInSatoshis > + 3 * feeInSatoshis + ) { // to prevent @dust error change transferred amount should be at least 3xfee. // if not - we just dont send change and it wil add to fee psbt.addOutput({ address: changeAddress, - value: unspentAmountSatoshi - amountToOutputSatoshi - feeInSatoshis, + value: unspentAmountSatoshi - amountToOutputSatoshi - feeInSatoshis }); } } @@ -133,26 +163,34 @@ exports.createHDSegwitTransaction = function(utxos, toAddress, amount, fixedFee, psbt.signInput(c, ourOutputs[c].keyPair); } - let tx = psbt.finalizeAllInputs().extractTransaction(); + const tx = psbt.finalizeAllInputs().extractTransaction(); return tx.toHex(); }; -exports.createSegwitTransaction = function(utxos, toAddress, amount, fixedFee, WIF, changeAddress, sequence) { +exports.createSegwitTransaction = function( + utxos, + toAddress, + amount, + fixedFee, + WIF, + changeAddress, + sequence +) { changeAddress = changeAddress || exports.WIF2segwitAddress(WIF); if (sequence === undefined) { sequence = bitcoinjs.Transaction.DEFAULT_SEQUENCE; } - let feeInSatoshis = parseInt((fixedFee * 100000000).toFixed(0)); - let keyPair = bitcoinjs.ECPair.fromWIF(WIF); - let p2wpkh = _p2wpkh({ - pubkey: keyPair.publicKey, + const feeInSatoshis = parseInt((fixedFee * 100000000).toFixed(0)); + const keyPair = bitcoinjs.ECPair.fromWIF(WIF); + const p2wpkh = _p2wpkh({ + pubkey: keyPair.publicKey }); - let p2sh = _p2sh({ - redeem: p2wpkh, + const p2sh = _p2sh({ + redeem: p2wpkh }); - let psbt = new bitcoinjs.Psbt(); + const psbt = new bitcoinjs.Psbt(); psbt.setVersion(1); let unspentAmount = 0; for (const unspent of utxos) { @@ -167,16 +205,16 @@ exports.createSegwitTransaction = function(utxos, toAddress, amount, fixedFee, W sequence, witnessUtxo: { script: p2sh.output, - value: satoshis, + value: satoshis }, - redeemScript: p2wpkh.output, + redeemScript: p2wpkh.output }); unspentAmount += satoshis; } - let amountToOutput = parseInt(((amount - fixedFee) * 100000000).toFixed(0)); + const amountToOutput = parseInt(((amount - fixedFee) * 100000000).toFixed(0)); psbt.addOutput({ address: toAddress, - value: amountToOutput, + value: amountToOutput }); if (amountToOutput + feeInSatoshis < unspentAmount) { // sending less than we have, so the rest should go back @@ -186,7 +224,7 @@ exports.createSegwitTransaction = function(utxos, toAddress, amount, fixedFee, W // if not - we just dont send change and it wil add to fee psbt.addOutput({ address: changeAddress, - value: unspentAmount - amountToOutput - feeInSatoshis, + value: unspentAmount - amountToOutput - feeInSatoshis }); } } @@ -194,68 +232,74 @@ exports.createSegwitTransaction = function(utxos, toAddress, amount, fixedFee, W for (let c = 0; c < utxos.length; c++) { psbt.signInput(c, keyPair); } - let tx = psbt.finalizeAllInputs().extractTransaction(); + const tx = psbt.finalizeAllInputs().extractTransaction(); return tx.toHex(); }; -exports.createRBFSegwitTransaction = function(txhex, addressReplaceMap, feeDelta, WIF, utxodata) { +exports.createRBFSegwitTransaction = function( + txhex, + addressReplaceMap, + feeDelta, + WIF, + utxodata +) { if (feeDelta < 0) { - throw Error('replace-by-fee requires increased fee, not decreased'); + throw Error("replace-by-fee requires increased fee, not decreased"); } - let tx = bitcoinjs.Transaction.fromHex(txhex); + const tx = bitcoinjs.Transaction.fromHex(txhex); // looking for latest sequence number in inputs let highestSequence = 0; - for (let i of tx.ins) { + for (const i of tx.ins) { if (i.sequence > highestSequence) { highestSequence = i.sequence; } } - let keyPair = bitcoinjs.ECPair.fromWIF(WIF); - let p2wpkh = _p2wpkh({ - pubkey: keyPair.publicKey, + const keyPair = bitcoinjs.ECPair.fromWIF(WIF); + const p2wpkh = _p2wpkh({ + pubkey: keyPair.publicKey }); - let p2sh = _p2sh({ - redeem: p2wpkh, + const p2sh = _p2sh({ + redeem: p2wpkh }); // creating TX - let psbt = new bitcoinjs.Psbt(); + const psbt = new bitcoinjs.Psbt(); psbt.setVersion(1); - for (let unspent of tx.ins) { - let txid = Buffer.from(unspent.hash) + for (const unspent of tx.ins) { + const txid = Buffer.from(unspent.hash) .reverse() - .toString('hex'); - let index = unspent.index; - let amount = utxodata[txid][index]; + .toString("hex"); + const index = unspent.index; + const amount = utxodata[txid][index]; psbt.addInput({ hash: txid, index, sequence: highestSequence + 1, witnessUtxo: { script: p2sh.output, - value: amount, + value: amount }, - redeemScript: p2wpkh.output, + redeemScript: p2wpkh.output }); } - for (let o of tx.outs) { - let outAddress = bitcoinjs.address.fromOutputScript(o.script); + for (const o of tx.outs) { + const outAddress = bitcoinjs.address.fromOutputScript(o.script); if (addressReplaceMap[outAddress]) { // means this is DESTINATION address, not messing with it's amount // but replacing the address itseld psbt.addOutput({ address: addressReplaceMap[outAddress], - value: o.value, + value: o.value }); } else { // CHANGE address, so we deduct increased fee from here - let feeDeltaInSatoshi = parseInt((feeDelta * 100000000).toFixed(0)); + const feeDeltaInSatoshi = parseInt((feeDelta * 100000000).toFixed(0)); psbt.addOutput({ address: outAddress, - value: o.value - feeDeltaInSatoshi, + value: o.value - feeDeltaInSatoshi }); } } @@ -265,33 +309,33 @@ exports.createRBFSegwitTransaction = function(txhex, addressReplaceMap, feeDelta psbt.signInput(c, keyPair); } - let newTx = psbt.finalizeAllInputs().extractTransaction(); + const newTx = psbt.finalizeAllInputs().extractTransaction(); return newTx.toHex(); }; exports.generateNewSegwitAddress = function() { - let keyPair = bitcoinjs.ECPair.makeRandom(); - let address = bitcoinjs.payments.p2sh({ + const keyPair = bitcoinjs.ECPair.makeRandom(); + const address = bitcoinjs.payments.p2sh({ redeem: bitcoinjs.payments.p2wpkh({ - pubkey: keyPair.publicKey, - }), + pubkey: keyPair.publicKey + }) }).address; return { address: address, - WIF: keyPair.toWIF(), + WIF: keyPair.toWIF() }; }; exports.URI = function(paymentInfo) { - let uri = 'veles:'; + let uri = "veles:"; uri += paymentInfo.address; - uri += '?amount='; + uri += "?amount="; uri += parseFloat(paymentInfo.amount / 100000000); - uri += '&message='; + uri += "&message="; uri += encodeURIComponent(paymentInfo.message); if (paymentInfo.label) { - uri += '&label='; + uri += "&label="; uri += encodeURIComponent(paymentInfo.label); } @@ -299,19 +343,26 @@ exports.URI = function(paymentInfo) { }; exports.WIF2segwitAddress = function(WIF) { - let keyPair = bitcoinjs.ECPair.fromWIF(WIF); + const keyPair = bitcoinjs.ECPair.fromWIF(WIF); return bitcoinjs.payments.p2sh({ redeem: bitcoinjs.payments.p2wpkh({ - pubkey: keyPair.publicKey, - }), + pubkey: keyPair.publicKey + }) }).address; }; -exports.createTransaction = function(utxos, toAddress, _amount, _fixedFee, WIF, fromAddress) { - let fixedFee = toSatoshi(_fixedFee); - let amountToOutput = toSatoshi(_amount - _fixedFee); - let pk = bitcoinjs.ECPair.fromWIF(WIF); // eslint-disable-line new-cap - let txb = new bitcoinjs.TransactionBuilder(); +exports.createTransaction = function( + utxos, + toAddress, + _amount, + _fixedFee, + WIF, + fromAddress +) { + const fixedFee = toSatoshi(_fixedFee); + const amountToOutput = toSatoshi(_amount - _fixedFee); + const pk = bitcoinjs.ECPair.fromWIF(WIF); // eslint-disable-line new-cap + const txb = new bitcoinjs.TransactionBuilder(); txb.setVersion(1); let unspentAmount = 0; for (const unspent of utxos) { @@ -331,9 +382,9 @@ exports.createTransaction = function(utxos, toAddress, _amount, _fixedFee, WIF, for (let c = 0; c < utxos.length; c++) { txb.sign({ - prevOutScriptType: 'p2pkh', + prevOutScriptType: "p2pkh", vin: c, - keyPair: pk, + keyPair: pk }); } diff --git a/package-lock.json b/package-lock.json index 93163814163..3342196e426 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1222,9 +1222,9 @@ } }, "@react-native-community/async-storage": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@react-native-community/async-storage/-/async-storage-1.6.2.tgz", - "integrity": "sha512-EJGsbrHubK1mGxPjWB74AaHAd5m9I+Gg2RRPZzMK6org7QOU9WOBnIMFqoeVto3hKOaEPlk8NV74H6G34/2pZQ==" + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@react-native-community/async-storage/-/async-storage-1.7.1.tgz", + "integrity": "sha512-/oX/x+EU4xNaqIaC/epVKzO8XghzImPA7l8cLz3USEFmtFiXFjBbTeeIFjjEm/u4/cv38Wi1xMEa10PHIWygRg==" }, "@react-native-community/blur": { "version": "3.3.1", @@ -1288,6 +1288,64 @@ "prettier": "1.16.4" }, "dependencies": { + "@typescript-eslint/eslint-plugin": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz", + "integrity": "sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "1.13.0", + "eslint-utils": "^1.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^2.0.1", + "tsutils": "^3.7.0" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", + "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-scope": "^4.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz", + "integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "1.13.0", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", + "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + } + }, "babel-eslint": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.1.tgz", @@ -1342,6 +1400,12 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true } } }, @@ -1410,6 +1474,15 @@ "version": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git#b8baa79ba3b3859c9353c9dee7f01392b989a530", "from": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git" }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, "@sentry/browser": { "version": "5.9.0", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.9.0.tgz", @@ -1664,6 +1737,12 @@ "@types/node": "*" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, "@types/debug": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", @@ -1708,9 +1787,9 @@ "integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==" }, "@types/json-schema": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz", - "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", "dev": true }, "@types/node": { @@ -1718,6 +1797,12 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.8.tgz", "integrity": "sha512-XLla8N+iyfjvsa0KKV+BP/iGSoTmwxsu5Ci5sM33z9TjohF72DEz95iNvD6pPmemvbQgxAv/909G73gUn8QR7w==" }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, "@types/restify": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/@types/restify/-/restify-4.3.6.tgz", @@ -1760,55 +1845,104 @@ "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==" }, "@typescript-eslint/eslint-plugin": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz", - "integrity": "sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.26.0.tgz", + "integrity": "sha512-4yUnLv40bzfzsXcTAtZyTjbiGUXMrcIJcIMioI22tSOyAxpdXiZ4r7YQUU8Jj6XXrLz9d5aMHPQf5JFR7h27Nw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "1.13.0", - "eslint-utils": "^1.3.1", + "@typescript-eslint/experimental-utils": "2.26.0", "functional-red-black-tree": "^1.0.1", - "regexpp": "^2.0.1", - "tsutils": "^3.7.0" + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" + }, + "dependencies": { + "regexpp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", + "dev": true + } } }, "@typescript-eslint/experimental-utils": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", - "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.26.0.tgz", + "integrity": "sha512-RELVoH5EYd+JlGprEyojUv9HeKcZqF7nZUGSblyAw1FwOGNnmQIU8kxJ69fttQvEwCsX5D6ECJT8GTozxrDKVQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "1.13.0", - "eslint-scope": "^4.0.0" + "@typescript-eslint/typescript-estree": "2.26.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", + "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + } } }, "@typescript-eslint/parser": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz", - "integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.26.0.tgz", + "integrity": "sha512-+Xj5fucDtdKEVGSh9353wcnseMRkPpEAOY96EEenN7kJVrLqy/EVwtIh3mxcUz8lsFXW1mT5nN5vvEam/a5HiQ==", "dev": true, "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "1.13.0", - "@typescript-eslint/typescript-estree": "1.13.0", - "eslint-visitor-keys": "^1.0.0" + "@typescript-eslint/experimental-utils": "2.26.0", + "@typescript-eslint/typescript-estree": "2.26.0", + "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/typescript-estree": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", - "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.26.0.tgz", + "integrity": "sha512-3x4SyZCLB4zsKsjuhxDLeVJN6W29VwBnYpCsZ7vIdPel9ZqLfIZJgJXO47MNUkurGpQuIBALdPQKtsSnWpE1Yg==", "dev": true, "requires": { - "lodash.unescape": "4.0.1", - "semver": "5.5.0" + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^6.3.0", + "tsutils": "^3.17.1" }, "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -2010,6 +2144,12 @@ "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", @@ -3555,6 +3695,59 @@ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.2.0.tgz", "integrity": "sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ==" }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -3699,6 +3892,12 @@ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -4053,6 +4252,12 @@ } } }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, "dayjs": { "version": "1.8.14", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.14.tgz", @@ -4380,6 +4585,12 @@ "version": "git+https://github.com/BlueWallet/rn-electrum-client.git#d194ff69195ccc86f72088ea3712179b4be9cbb4", "from": "git+https://github.com/BlueWallet/rn-electrum-client.git" }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, "elliptic": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", @@ -4783,6 +4994,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.0.0.tgz", "integrity": "sha512-vDrcCFE3+2ixNT5H83g28bO/uYAwibJxerXPj+E7op4qzBCsAV36QfvdAyVOoNxKAH2Os/e01T/2x++V0LPukA==", + "dev": true, "requires": { "get-stdin": "^6.0.0" } @@ -5660,6 +5872,15 @@ "locate-path": "^3.0.0" } }, + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "requires": { + "semver-regex": "^2.0.0" + } + }, "findit": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findit/-/findit-2.0.0.tgz", @@ -6397,10 +6618,17 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, "get-stdin": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==" + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true }, "get-stream": { "version": "4.1.0", @@ -6854,103 +7082,275 @@ } } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", - "dev": true - }, - "image-size": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", - "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" - }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, - "immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "husky": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.3.tgz", + "integrity": "sha512-VxTsSTRwYveKXN4SaH1/FefRJYCtx+wx04sSVcOpD7N2zjoHxa+cEJ07Qg5NmV3HAK+IRKOyNVpi2YBIVccIfQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.5.1", + "cosmiconfig": "^6.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "image-size": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", + "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, + "immutable": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", + "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", "requires": { "ansi-escapes": "^3.2.0", "chalk": "^2.4.2", @@ -7177,6 +7577,23 @@ "resolved": "https://registry.npmjs.org/is-object/-/is-object-0.1.2.tgz", "integrity": "sha1-AO+8CIFsM8/ErIJR0TLhDcZQmNc=" }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + }, + "dependencies": { + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + } + } + }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", @@ -7225,6 +7642,12 @@ "has": "^1.0.1" } }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", @@ -8403,105 +8826,581 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-0.1.19.tgz", "integrity": "sha1-YT+2hjmyaklKxTJT4Vsaa9iK2oU=" }, - "level-fix-range": { + "level-fix-range": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/level-fix-range/-/level-fix-range-2.0.0.tgz", + "integrity": "sha1-xBfWIVlEIVGhnZojZ4aPFyTC1Ug=", + "requires": { + "clone": "~0.1.9" + } + }, + "object-keys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.2.0.tgz", + "integrity": "sha1-zd7AKZiwkb5CvxA1rjLknxy26mc=", + "requires": { + "foreach": "~2.0.1", + "indexof": "~0.0.1", + "is": "~0.2.6" + } + }, + "xtend": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.0.6.tgz", + "integrity": "sha1-XqZXptukRwacLlnFihE4ywxebO4=", + "requires": { + "is-object": "~0.1.2", + "object-keys": "~0.2.0" + } + } + } + }, + "levelup": { + "version": "0.18.6", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-0.18.6.tgz", + "integrity": "sha1-5qAcsIlhbI7MApHCqb0/DETj5es=", + "requires": { + "bl": "~0.8.1", + "deferred-leveldown": "~0.2.0", + "errno": "~0.1.1", + "prr": "~0.0.0", + "readable-stream": "~1.0.26", + "semver": "~2.3.1", + "xtend": "~3.0.0" + }, + "dependencies": { + "bl": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.8.2.tgz", + "integrity": "sha1-yba8oI0bwuoA/Ir7Txpf0eHGbk4=", + "requires": { + "readable-stream": "~1.0.26" + } + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "semver": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz", + "integrity": "sha1-uYSPJdbPNjMwc+ye+IVtQvEjPlI=" + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=" + } + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "requires": { + "immediate": "~3.0.5" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "lint-staged": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.1.1.tgz", + "integrity": "sha512-wAeu/ePaBAOfwM2+cVbgPWDtn17B0Sxiv0NvNEqDAIvB8Yhvl60vafKFiK4grcYn87K1iK+a0zVoETvKbdT9/Q==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "commander": "^4.0.1", + "cosmiconfig": "^6.0.0", + "debug": "^4.1.1", + "dedent": "^0.7.0", + "execa": "^3.4.0", + "listr": "^0.14.3", + "log-symbols": "^3.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", + "please-upgrade-node": "^3.2.0", + "string-argv": "0.3.1", + "stringify-object": "^3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/level-fix-range/-/level-fix-range-2.0.0.tgz", - "integrity": "sha1-xBfWIVlEIVGhnZojZ4aPFyTC1Ug=", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "requires": { - "clone": "~0.1.9" + "shebang-regex": "^3.0.0" } }, - "object-keys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.2.0.tgz", - "integrity": "sha1-zd7AKZiwkb5CvxA1rjLknxy26mc=", + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, "requires": { - "foreach": "~2.0.1", - "indexof": "~0.0.1", - "is": "~0.2.6" + "has-flag": "^4.0.0" } }, - "xtend": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.0.6.tgz", - "integrity": "sha1-XqZXptukRwacLlnFihE4ywxebO4=", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "requires": { - "is-object": "~0.1.2", - "object-keys": "~0.2.0" + "is-number": "^7.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" } } } }, - "levelup": { - "version": "0.18.6", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-0.18.6.tgz", - "integrity": "sha1-5qAcsIlhbI7MApHCqb0/DETj5es=", + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, "requires": { - "bl": "~0.8.1", - "deferred-leveldown": "~0.2.0", - "errno": "~0.1.1", - "prr": "~0.0.0", - "readable-stream": "~1.0.26", - "semver": "~2.3.1", - "xtend": "~3.0.0" + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" }, "dependencies": { - "bl": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.8.2.tgz", - "integrity": "sha1-yba8oI0bwuoA/Ir7Txpf0eHGbk4=", + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, "requires": { - "readable-stream": "~1.0.26" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, - "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=" + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "chalk": "^1.0.0" } }, - "semver": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz", - "integrity": "sha1-uYSPJdbPNjMwc+ye+IVtQvEjPlI=" + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=" + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true } } }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, "requires": { - "immediate": "~3.0.5" + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" } }, "load-json-file": { @@ -8631,6 +9530,38 @@ "chalk": "^2.0.1" } }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, "logkitty": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.6.1.tgz", @@ -10393,6 +11324,12 @@ } } }, + "opencollective-postinstall": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz", + "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==", + "dev": true + }, "opn": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", @@ -10534,6 +11471,12 @@ "p-limit": "^2.0.0" } }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", @@ -10752,6 +11695,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -10786,6 +11735,15 @@ "find-up": "^3.0.0" } }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, "plist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", @@ -10896,6 +11854,47 @@ "vue-eslint-parser": "^2.0.2" }, "dependencies": { + "@typescript-eslint/experimental-utils": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", + "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-scope": "^4.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz", + "integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "1.13.0", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", + "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, "acorn": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", @@ -12966,6 +13965,12 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, "semver-diff": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", @@ -12974,6 +13979,12 @@ "semver": "^5.0.3" } }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -13992,6 +15003,12 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", @@ -14060,6 +15077,17 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -14085,6 +15113,12 @@ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -14998,6 +16032,12 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, "widest-line": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", @@ -15172,6 +16212,32 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, + "yaml": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.8.3.tgz", + "integrity": "sha512-X/v7VDnK+sxbQ2Imq4Jt2PRUsRsP7UcpSl3Llg6+NRRqWLIvxkMFYtH1FmvwNGYRKKPa+EPA4qDBlI9WVG1UKw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.7" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true + } + } + }, "yargs": { "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", diff --git a/package.json b/package.json index d9e666666ff..e19b4c51ac0 100644 --- a/package.json +++ b/package.json @@ -5,19 +5,24 @@ "@babel/core": "^7.5.0", "@babel/runtime": "^7.5.1", "@react-native-community/eslint-config": "^0.0.5", + "@typescript-eslint/eslint-plugin": "^2.26.0", + "@typescript-eslint/parser": "^2.26.0", "babel-cli": "^6.26.0", "babel-eslint": "^10.0.2", "babel-jest": "^24.8.0", "babel-preset-flow": "^6.23.0", "eslint": "^6.0.1", + "eslint-config-prettier": "^6.0.0", "eslint-plugin-babel": "^5.3.0", "eslint-plugin-import": "^2.18.0", "eslint-plugin-node": "^9.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-react": "^7.14.2", "flow-bin": "^0.102.0", + "husky": "^4.2.3", "jest": "^24.8.0", "jetifier": "^1.6.3", + "lint-staged": "^10.1.1", "metro-react-native-babel-preset": "^0.56.0", "prettier-eslint-cli": "^5.0.0", "react-test-renderer": "16.8.6", @@ -32,9 +37,10 @@ "android": "react-native run-android", "ios": "react-native run-ios", "postinstall": "./node_modules/.bin/rn-nodeify --install buffer,events,process,stream,util,inherits,fs,path --hack; npm run releasenotes2json; npm run podinstall; npx jetify", - "test": "npm run unit && npm run jest && npm run lint", + "test": "npm run unit && npm run jest", "jest": "node node_modules/jest/bin/jest.js tests/integration/*", - "lint": "./node_modules/.bin/eslint *.js screen/**/*.js screen/ class/ models/ loc/ tests/integration/ --fix", + "lint": "eslint *.js screen/**/*.js screen/ class/ models/ loc/ tests/integration/", + "lint:fix": "npm run lint --fix", "unit": "./node_modules/.bin/mocha tests/unit/*" }, "jest": { @@ -70,7 +76,6 @@ "dayjs": "1.8.14", "ecurve": "1.0.6", "electrum-client": "git+https://github.com/BlueWallet/rn-electrum-client.git", - "eslint-config-prettier": "6.0.0", "eslint-config-standard": "12.0.0", "eslint-config-standard-react": "7.0.2", "eslint-plugin-prettier": "3.1.0", @@ -107,7 +112,7 @@ "react-native-popup-menu-android": "1.0.3", "react-native-privacy-snapshot": "git+https://github.com/BlueWallet/react-native-privacy-snapshot.git", "react-native-prompt-android": "git+https://github.com/marcosrdz/react-native-prompt-android.git", - "react-native-qrcode-svg": "5.1.2", + "react-native-qrcode-svg": "5.3.2", "react-native-quick-actions": "0.3.12", "react-native-randombytes": "3.5.3", "react-native-rate": "1.1.7", @@ -151,5 +156,15 @@ "_stream_duplex": "readable-stream/duplex", "_stream_passthrough": "readable-stream/passthrough", "stream": "stream-browserify" + }, + "lint-staged": { + "./**/*.{ts,tsx,js,jsx}": [ + "npm run lint:fix" + ] + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } } } diff --git a/prompt.js b/prompt.js index 366962bb764..79f0b5e9635 100644 --- a/prompt.js +++ b/prompt.js @@ -1,37 +1,37 @@ -import prompt from 'react-native-prompt-android'; +import prompt from "react-native-prompt-android"; -module.exports = (title, text, isCancelable = true, type = 'secure-text') => { +module.exports = (title, text, isCancelable = true, type = "secure-text") => { return new Promise((resolve, reject) => { const buttons = isCancelable ? [ { - text: 'Cancel', + text: "Cancel", onPress: () => { - reject(Error('Cancel Pressed')); + reject(Error("Cancel Pressed")); }, - style: 'cancel', + style: "cancel" }, { - text: 'OK', + text: "OK", onPress: password => { - console.log('OK Pressed, password: ' + password); + console.log("OK Pressed, password: " + password); resolve(password); - }, - }, + } + } ] : [ { - text: 'OK', + text: "OK", onPress: password => { - console.log('OK Pressed, password: ' + password); + console.log("OK Pressed, password: " + password); resolve(password); - }, - }, + } + } ]; prompt(title, text, buttons, { type: type, - cancelable: isCancelable, + cancelable: isCancelable }); }); }; diff --git a/react-native.config.js b/react-native.config.js index daa0bcdb956..329b713dd48 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -2,18 +2,18 @@ module.exports = { dependencies: { appcenter: { platforms: { - android: null, // disable Android platform, other platforms will still autolink if provided - }, + android: null // disable Android platform, other platforms will still autolink if provided + } }, - 'appcenter-analytics': { + "appcenter-analytics": { platforms: { - android: null, // disable Android platform, other platforms will still autolink if provided - }, + android: null // disable Android platform, other platforms will still autolink if provided + } }, - 'appcenter-crashes': { + "appcenter-crashes": { platforms: { - android: null, // disable Android platform, other platforms will still autolink if provided - }, - }, - }, + android: null // disable Android platform, other platforms will still autolink if provided + } + } + } }; diff --git a/screen/plausibledeniability.js b/screen/plausibledeniability.js index 0d61fa850fa..3137b5959ab 100644 --- a/screen/plausibledeniability.js +++ b/screen/plausibledeniability.js @@ -1,30 +1,38 @@ /* global alert */ -import React, { Component } from 'react'; -import { ScrollView } from 'react-native'; -import { BlueLoading, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle, BlueSpacing20 } from '../BlueComponents'; -import PropTypes from 'prop-types'; +import React, { Component } from "react"; +import { ScrollView } from "react-native"; +import { + BlueLoading, + BlueButton, + SafeBlueArea, + BlueCard, + BlueText, + BlueNavigationStyle, + BlueSpacing20 +} from "../BlueComponents"; +import PropTypes from "prop-types"; /** @type {AppStorage} */ -let BlueApp = require('../BlueApp'); -let prompt = require('../prompt'); -let EV = require('../events'); -let loc = require('../loc'); +const BlueApp = require("../BlueApp"); +const prompt = require("../prompt"); +const EV = require("../events"); +const loc = require("../loc"); export default class PlausibleDeniability extends Component { static navigationOptions = { ...BlueNavigationStyle(), - title: loc.plausibledeniability.title, + title: loc.plausibledeniability.title }; constructor(props) { super(props); this.state = { - isLoading: true, + isLoading: true }; } async componentDidMount() { this.setState({ - isLoading: false, + isLoading: false }); } @@ -34,7 +42,7 @@ export default class PlausibleDeniability extends Component { } return ( - + {loc.plausibledeniability.help} @@ -47,22 +55,29 @@ export default class PlausibleDeniability extends Component { { - let p1 = await prompt(loc.plausibledeniability.create_password, loc.plausibledeniability.create_password_explanation); + const p1 = await prompt( + loc.plausibledeniability.create_password, + loc.plausibledeniability.create_password_explanation + ); if (p1 === BlueApp.cachedPassword) { - return alert(loc.plausibledeniability.password_should_not_match); + return alert( + loc.plausibledeniability.password_should_not_match + ); } if (!p1) { return; } - let p2 = await prompt(loc.plausibledeniability.retype_password); + const p2 = await prompt( + loc.plausibledeniability.retype_password + ); if (p1 !== p2) { return alert(loc.plausibledeniability.passwords_do_not_match); } @@ -71,7 +86,7 @@ export default class PlausibleDeniability extends Component { EV(EV.enum.WALLETS_COUNT_CHANGED); EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); alert(loc.plausibledeniability.success); - this.props.navigation.navigate('Wallets'); + this.props.navigation.navigate("Wallets"); }} /> @@ -84,6 +99,6 @@ export default class PlausibleDeniability extends Component { PlausibleDeniability.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/receive/details.js b/screen/receive/details.js index 118038940f3..e8ccdee26c7 100644 --- a/screen/receive/details.js +++ b/screen/receive/details.js @@ -1,7 +1,7 @@ -import React, { Component } from 'react'; -import { View, InteractionManager, ScrollView } from 'react-native'; -import QRCode from 'react-native-qrcode-svg'; -import bip21 from 'bip21'; +import React, { Component } from "react"; +import { View, InteractionManager, ScrollView } from "react-native"; +import QRCode from "react-native-qrcode-svg"; +import bip21 from "bip21"; import { BlueLoading, SafeBlueArea, @@ -10,42 +10,42 @@ import { BlueButtonLink, BlueNavigationStyle, BlueSpacing10, - is, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import Privacy from '../../Privacy'; -import Share from 'react-native-share'; -import { Chain } from '../../models/bitcoinUnits'; + is +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import Privacy from "../../Privacy"; +import Share from "react-native-share"; +import { Chain } from "../../models/bitcoinUnits"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); export default class ReceiveDetails extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), title: loc.receive.header, - headerLeft: null, + headerLeft: null }); constructor(props) { super(props); - let secret = props.navigation.state.params.secret || ''; + const secret = props.navigation.state.params.secret || ""; this.state = { secret: secret, - addressText: '', - bip21encoded: undefined, + addressText: "", + bip21encoded: undefined }; } async componentDidMount() { Privacy.enableBlur(); - console.log('receive/details - componentDidMount'); + console.log("receive/details - componentDidMount"); { let address; let wallet; - for (let w of BlueApp.getWallets()) { + for (const w of BlueApp.getWallets()) { if (w.getSecret() === this.state.secret) { // found our wallet wallet = w; @@ -55,27 +55,37 @@ export default class ReceiveDetails extends Component { if (wallet.getAddressForTransaction) { if (wallet.chain === Chain.ONCHAIN) { try { - address = await Promise.race([wallet.getAddressForTransaction(), BlueApp.sleep(1000)]); + address = await Promise.race([ + wallet.getAddressForTransaction(), + BlueApp.sleep(1000) + ]); } catch (_) {} if (!address) { // either sleep expired or getAddressAsync threw an exception - console.warn('either sleep expired or getAddressAsync threw an exception'); + console.warn( + "either sleep expired or getAddressAsync threw an exception" + ); address = wallet.getAddressForTransaction(); } else { BlueApp.saveToDisk(); // caching whatever getAddressAsync() generated internally } this.setState({ address: address, - addressText: address, + addressText: address }); } else if (wallet.chain === Chain.OFFCHAIN) { try { - await Promise.race([wallet.getAddressForTransaction(), BlueApp.sleep(1000)]); + await Promise.race([ + wallet.getAddressForTransaction(), + BlueApp.sleep(1000) + ]); address = wallet.getAddress(); } catch (_) {} if (!address) { // either sleep expired or getAddressAsync threw an exception - console.warn('either sleep expired or getAddressAsync threw an exception'); + console.warn( + "either sleep expired or getAddressAsync threw an exception" + ); address = wallet.getAddress(); } else { BlueApp.saveToDisk(); // caching whatever getAddressAsync() generated internally @@ -83,12 +93,12 @@ export default class ReceiveDetails extends Component { } this.setState({ address: address, - addressText: address, + addressText: address }); } else if (wallet.getAddress) { this.setState({ address: wallet.getAddress(), - addressText: wallet.getAddress(), + addressText: wallet.getAddress() }); } } @@ -107,32 +117,44 @@ export default class ReceiveDetails extends Component { render() { return ( - - + + {this.state.bip21encoded === undefined ? ( - + ) : ( (this.qrCodeSVG = c)} /> )} - + { - this.props.navigation.navigate('ReceiveAmount', { - address: this.state.address, + this.props.navigation.navigate("ReceiveAmount", { + address: this.state.address }); }} /> @@ -140,21 +162,25 @@ export default class ReceiveDetails extends Component { { if (this.qrCodeSVG === undefined) { - Share.open({ message: `veles:${this.state.address}` }).catch(error => console.log(error)); + Share.open({ + message: `veles:${this.state.address}` + }).catch(error => console.log(error)); } else { InteractionManager.runAfterInteractions(async () => { this.qrCodeSVG.toDataURL(data => { - let shareImageBase64 = { + const shareImageBase64 = { message: `veles:${this.state.address}`, - url: `data:image/png;base64,${data}`, + url: `data:image/png;base64,${data}` }; - Share.open(shareImageBase64).catch(error => console.log(error)); + Share.open(shareImageBase64).catch(error => + console.log(error) + ); }); }); } @@ -175,8 +201,8 @@ ReceiveDetails.propTypes = { navigate: PropTypes.func, state: PropTypes.shape({ params: PropTypes.shape({ - secret: PropTypes.string, - }), - }), - }), + secret: PropTypes.string + }) + }) + }) }; diff --git a/screen/receive/receiveAmount.js b/screen/receive/receiveAmount.js index fddc3c51bf6..162aaa1a2a7 100644 --- a/screen/receive/receiveAmount.js +++ b/screen/receive/receiveAmount.js @@ -1,7 +1,14 @@ -import React, { Component } from 'react'; -import { View, Share, TextInput, KeyboardAvoidingView, Dimensions, ScrollView } from 'react-native'; -import QRCode from 'react-native-qrcode-svg'; -import bip21 from 'bip21'; +import React, { Component } from "react"; +import { + View, + Share, + TextInput, + KeyboardAvoidingView, + Dimensions, + ScrollView +} from "react-native"; +import QRCode from "react-native-qrcode-svg"; +import bip21 from "bip21"; import { SafeBlueArea, BlueCard, @@ -9,42 +16,43 @@ import { BlueNavigationStyle, BlueBitcoinAmount, BlueText, - BlueCopyTextToClipboard, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import Privacy from '../../Privacy'; + BlueCopyTextToClipboard +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import Privacy from "../../Privacy"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); -const { width } = Dimensions.get('window'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); + +const { width } = Dimensions.get("window"); export default class ReceiveAmount extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), title: loc.receive.header, - headerLeft: null, + headerLeft: null }); static propTypes = { navigation: PropTypes.shape({ state: PropTypes.shape({ params: PropTypes.shape({ - address: PropTypes.string, - }), - }), - }), + address: PropTypes.string + }) + }) + }) }; constructor(props) { super(props); - let address = props.navigation.state.params.address; + const address = props.navigation.state.params.address; this.state = { address: address, addressText: address, amount: undefined, label: undefined, - amountSet: false, + amountSet: false }; } @@ -68,7 +76,7 @@ export default class ReceiveAmount extends Component { this.setState({ label: text })} placeholderTextColor={BlueApp.settings.alternativeTextColor} placeholder={loc.receive.details.label} - value={this.state.label || ''} + value={this.state.label || ""} numberOfLines={1} - style={{ flex: 1, color: BlueApp.settings.foregroundColor, marginHorizontal: 8, minHeight: 33 }} + style={{ + flex: 1, + color: BlueApp.settings.foregroundColor, + marginHorizontal: 8, + minHeight: 33 + }} editable={!this.state.isLoading} /> @@ -97,7 +110,10 @@ export default class ReceiveAmount extends Component { onPress={() => { this.setState({ amountSet: true, - bip21: bip21.encode(this.state.address, { amount: this.state.amount, label: this.state.label }), + bip21: bip21.encode(this.state.address, { + amount: this.state.amount, + label: this.state.label + }) }); }} /> @@ -108,22 +124,36 @@ export default class ReceiveAmount extends Component { renderWithSetAmount() { return ( - - + + {this.state.label} - + - + @@ -134,26 +164,34 @@ export default class ReceiveAmount extends Component { return ( - + this.setState({ amount: text })} disabled={this.state.amountSet} /> - {this.state.amountSet ? this.renderWithSetAmount() : this.renderDefault()} + {this.state.amountSet + ? this.renderWithSetAmount() + : this.renderDefault()} {this.state.amountSet && ( { Share.share({ - message: this.state.bip21, + message: this.state.bip21 }); }} title={loc.receive.details.share} diff --git a/screen/selftest.js b/screen/selftest.js index 8fcdeca5214..b983ff9e58b 100644 --- a/screen/selftest.js +++ b/screen/selftest.js @@ -1,78 +1,107 @@ -import React, { Component } from 'react'; -import { ScrollView, View } from 'react-native'; -import { BlueLoading, BlueSpacing20, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../BlueComponents'; -import PropTypes from 'prop-types'; -import { SegwitP2SHWallet, LegacyWallet, HDSegwitP2SHWallet, HDSegwitBech32Wallet } from '../class'; -const bitcoin = require('bitcoinjs-lib'); -let BigNumber = require('bignumber.js'); -let encryption = require('../encryption'); -let BlueElectrum = require('../BlueElectrum'); +import React, { Component } from "react"; +import { ScrollView, View } from "react-native"; +import { + BlueLoading, + BlueSpacing20, + SafeBlueArea, + BlueCard, + BlueText, + BlueNavigationStyle +} from "../BlueComponents"; +import PropTypes from "prop-types"; +import { + SegwitP2SHWallet, + LegacyWallet, + HDSegwitP2SHWallet, + HDSegwitBech32Wallet +} from "../class"; + +const bitcoin = require("bitcoinjs-lib"); +const BigNumber = require("bignumber.js"); +const encryption = require("../encryption"); +const BlueElectrum = require("../BlueElectrum"); export default class Selftest extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(), - title: 'Self test', + title: "Self test" }); constructor(props) { super(props); this.state = { - isLoading: true, + isLoading: true }; } async componentDidMount() { - let errorMessage = ''; + let errorMessage = ""; let isOk = true; try { - if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { - let uniqs = {}; - let w = new SegwitP2SHWallet(); + if ( + typeof navigator !== "undefined" && + navigator.product === "ReactNative" + ) { + const uniqs = {}; + const w = new SegwitP2SHWallet(); for (let c = 0; c < 1000; c++) { await w.generate(); if (uniqs[w.getSecret()]) { - errorMessage += 'failed to generate unique private key; '; + errorMessage += "failed to generate unique private key; "; isOk = false; break; } uniqs[w.getSecret()] = 1; } } else { - console.warn('skipping RN-specific test'); + console.warn("skipping RN-specific test"); } // - if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { + if ( + typeof navigator !== "undefined" && + navigator.product === "ReactNative" + ) { await BlueElectrum.ping(); await BlueElectrum.waitTillConnected(); - let addr4elect = '3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK'; - let electrumBalance = await BlueElectrum.getBalanceByAddress(addr4elect); + const addr4elect = "3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK"; + const electrumBalance = await BlueElectrum.getBalanceByAddress( + addr4elect + ); if (electrumBalance.confirmed !== 51432) - throw new Error('BlueElectrum getBalanceByAddress failure, got ' + JSON.stringify(electrumBalance)); - - let electrumTxs = await BlueElectrum.getTransactionsByAddress(addr4elect); - if (electrumTxs.length !== 1) throw new Error('BlueElectrum getTransactionsByAddress failure, got ' + JSON.stringify(electrumTxs)); + throw new Error( + "BlueElectrum getBalanceByAddress failure, got " + + JSON.stringify(electrumBalance) + ); + + const electrumTxs = await BlueElectrum.getTransactionsByAddress( + addr4elect + ); + if (electrumTxs.length !== 1) + throw new Error( + "BlueElectrum getTransactionsByAddress failure, got " + + JSON.stringify(electrumTxs) + ); } else { - console.warn('skipping RN-specific test'); + console.warn("skipping RN-specific test"); } // let l = new LegacyWallet(); - l.setSecret('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct'); - if (l.getAddress() !== '19AAjaTUbRjQCMuVczepkoPswiZRhjtg31') { - errorMessage += 'failed to generate legacy address from WIF; '; + l.setSecret("Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct"); + if (l.getAddress() !== "19AAjaTUbRjQCMuVczepkoPswiZRhjtg31") { + errorMessage += "failed to generate legacy address from WIF; "; isOk = false; } - // - // utxos as received from blockcypher let utxos = [ { - tx_hash: '2f445cf016fa2772db7d473bff97515355b4e6148e1c980ce351d47cf54c517f', + tx_hash: + "2f445cf016fa2772db7d473bff97515355b4e6148e1c980ce351d47cf54c517f", block_height: 523186, tx_input_n: -1, tx_output_n: 1, @@ -80,19 +109,19 @@ export default class Selftest extends Component { ref_balance: 100000, spent: false, confirmations: 215, - confirmed: '2018-05-18T03:16:34Z', - double_spend: false, - }, + confirmed: "2018-05-18T03:16:34Z", + double_spend: false + } ]; - let toAddr = '1GX36PGBUrF8XahZEGQqHqnJGW2vCZteoB'; + let toAddr = "1GX36PGBUrF8XahZEGQqHqnJGW2vCZteoB"; let amount = 0.0009; let fee = 0.0001; let txHex = l.createTx(utxos, amount, fee, toAddr); if ( txHex !== - '01000000017f514cf57cd451e30c981c8e14e6b455535197ff3b477ddb7227fa16f05c442f010000006b483045022100b9a6545847bd30418c133437c7660a6676afafe6e7e837a37ef2ead931ebd586022056bc43cbf71855d0719f54151c8fcaaaa03367ecafdd7296dbe39f042e432f4f012103aea0dfd576151cb399347aa6732f8fdf027b9ea3ea2e65fb754803f776e0a509ffffffff01905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac00000000' + "01000000017f514cf57cd451e30c981c8e14e6b455535197ff3b477ddb7227fa16f05c442f010000006b483045022100b9a6545847bd30418c133437c7660a6676afafe6e7e837a37ef2ead931ebd586022056bc43cbf71855d0719f54151c8fcaaaa03367ecafdd7296dbe39f042e432f4f012103aea0dfd576151cb399347aa6732f8fdf027b9ea3ea2e65fb754803f776e0a509ffffffff01905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac00000000" ) { - errorMessage += 'failed to create TX from legacy address; '; + errorMessage += "failed to create TX from legacy address; "; isOk = false; } @@ -100,69 +129,74 @@ export default class Selftest extends Component { // utxos as received from blockcypher utxos = [ { - amount: '0.002', + amount: "0.002", block_height: 523416, confirmations: 6, - confirmed: '2018-05-19T15:46:43Z', + confirmed: "2018-05-19T15:46:43Z", double_spend: false, ref_balance: 300000, spent: false, - tx_hash: 'dc3605040a03724bc584ed43bc22a559f5d32a1b0708ca05b20b9018fdd523ef', + tx_hash: + "dc3605040a03724bc584ed43bc22a559f5d32a1b0708ca05b20b9018fdd523ef", tx_input_n: -1, tx_output_n: 0, - txid: 'dc3605040a03724bc584ed43bc22a559f5d32a1b0708ca05b20b9018fdd523ef', + txid: + "dc3605040a03724bc584ed43bc22a559f5d32a1b0708ca05b20b9018fdd523ef", value: 200000, - vout: 0, + vout: 0 }, { - amount: '0.001', + amount: "0.001", block_height: 523186, confirmations: 6, - confirmed: '2018-05-18T03:16:34Z', + confirmed: "2018-05-18T03:16:34Z", double_spend: false, ref_balance: 100000, spent: false, - tx_hash: 'c473c104febfe6621804976d1082a1468c1198d0339e35f30a8ba1515d9eb017', + tx_hash: + "c473c104febfe6621804976d1082a1468c1198d0339e35f30a8ba1515d9eb017", tx_input_n: -1, tx_output_n: 0, - txid: 'c473c104febfe6621804976d1082a1468c1198d0339e35f30a8ba1515d9eb017', + txid: + "c473c104febfe6621804976d1082a1468c1198d0339e35f30a8ba1515d9eb017", value: 100000, - vout: 0, - }, + vout: 0 + } ]; - toAddr = '1GX36PGBUrF8XahZEGQqHqnJGW2vCZteoB'; + toAddr = "1GX36PGBUrF8XahZEGQqHqnJGW2vCZteoB"; amount = 0.0009; fee = 0.0001; try { txHex = l.createTx(utxos, amount, fee, toAddr); } catch (e) { - errorMessage += e.message + '; '; + errorMessage += e.message + "; "; isOk = false; } if ( txHex !== - '0100000002ef23d5fd18900bb205ca08071b2ad3f559a522bc43ed84c54b72030a040536dc000000006a47304402206b4f03e471d60dff19f4df1a8203ca97f6282658160034cea0f2b7d748c33d9802206058d23861dabdfb252c8df14249d1a2b00345dd90d32ab451cc3c6cfcb3b402012103aea0dfd576151cb399347aa6732f8fdf027b9ea3ea2e65fb754803f776e0a509ffffffff17b09e5d51a18b0af3359e33d098118c46a182106d97041862e6bffe04c173c4000000006b4830450221009785a61358a1ee7ab5885a98b111275226e0046a48b69980c4f53ecf99cdce0a02200503249e0b23d633ec1fbae5d41a0dcf9758dce3560066d1aee9ecfbfeefcfb7012103aea0dfd576151cb399347aa6732f8fdf027b9ea3ea2e65fb754803f776e0a509ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac400d0300000000001976a914597ce022baa887799951e0496c769d9cc0c759dc88ac00000000' + "0100000002ef23d5fd18900bb205ca08071b2ad3f559a522bc43ed84c54b72030a040536dc000000006a47304402206b4f03e471d60dff19f4df1a8203ca97f6282658160034cea0f2b7d748c33d9802206058d23861dabdfb252c8df14249d1a2b00345dd90d32ab451cc3c6cfcb3b402012103aea0dfd576151cb399347aa6732f8fdf027b9ea3ea2e65fb754803f776e0a509ffffffff17b09e5d51a18b0af3359e33d098118c46a182106d97041862e6bffe04c173c4000000006b4830450221009785a61358a1ee7ab5885a98b111275226e0046a48b69980c4f53ecf99cdce0a02200503249e0b23d633ec1fbae5d41a0dcf9758dce3560066d1aee9ecfbfeefcfb7012103aea0dfd576151cb399347aa6732f8fdf027b9ea3ea2e65fb754803f776e0a509ffffffff02905f0100000000001976a914aa381cd428a4e91327fd4434aa0a08ff131f1a5a88ac400d0300000000001976a914597ce022baa887799951e0496c769d9cc0c759dc88ac00000000" ) { - errorMessage += 'failed to create TX from legacy address; '; + errorMessage += "failed to create TX from legacy address; "; isOk = false; } // l = new SegwitP2SHWallet(); - l.setSecret('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct'); - if (l.getAddress() !== '34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53') { - errorMessage += 'failed to generate segwit P2SH address from WIF; '; + l.setSecret("Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct"); + if (l.getAddress() !== "34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53") { + errorMessage += "failed to generate segwit P2SH address from WIF; "; isOk = false; } // // utxos as received from blockcypher - let utxo = [ + const utxo = [ { - tx_hash: '0f5eea78fb19e72b55bd119252ff29fc16c503d0e956a9c1b5b2ab0e95e0c323', + tx_hash: + "0f5eea78fb19e72b55bd119252ff29fc16c503d0e956a9c1b5b2ab0e95e0c323", block_height: 514991, tx_input_n: -1, tx_output_n: 2, @@ -170,24 +204,32 @@ export default class Selftest extends Component { ref_balance: 546, spent: false, confirmations: 9, - confirmed: '2018-03-24T18:13:36Z', - double_spend: false, - }, + confirmed: "2018-03-24T18:13:36Z", + double_spend: false + } ]; - let tx = l.createTx(utxo, 0.001, 0.0001, '1QHf8Gp3wfmFiSdEX4FtrssCGR68diN1cj'); - let txDecoded = bitcoin.Transaction.fromHex(tx); - let txid = txDecoded.getId(); + const tx = l.createTx( + utxo, + 0.001, + 0.0001, + "1QHf8Gp3wfmFiSdEX4FtrssCGR68diN1cj" + ); + const txDecoded = bitcoin.Transaction.fromHex(tx); + const txid = txDecoded.getId(); - if (txid !== '110f51d28d585e922adbf701cba802e549b8fe3a53fa5d62426ab42549c9b6de') { - errorMessage += 'created txid doesnt match; '; + if ( + txid !== + "110f51d28d585e922adbf701cba802e549b8fe3a53fa5d62426ab42549c9b6de" + ) { + errorMessage += "created txid doesnt match; "; isOk = false; } if ( tx !== - '0100000000010123c3e0950eabb2b5c1a956e9d003c516fc29ff529211bd552be719fb78ea5e0f0200000017160014597ce022baa887799951e0496c769d9cc0c759dc0000000001a0860100000000001976a914ff715fb722cb10646d80709aeac7f2f4ee00278f88ac02473044022075670317a0e5b5d4eef154b03db97396a64cbc6ef3b576d98367e1a83c1c488002206d6df1e8085fd711d6ea264de3803340f80fa2c6e30683879d9ad40f3228c56c012103aea0dfd576151cb399347aa6732f8fdf027b9ea3ea2e65fb754803f776e0a50900000000' + "0100000000010123c3e0950eabb2b5c1a956e9d003c516fc29ff529211bd552be719fb78ea5e0f0200000017160014597ce022baa887799951e0496c769d9cc0c759dc0000000001a0860100000000001976a914ff715fb722cb10646d80709aeac7f2f4ee00278f88ac02473044022075670317a0e5b5d4eef154b03db97396a64cbc6ef3b576d98367e1a83c1c488002206d6df1e8085fd711d6ea264de3803340f80fa2c6e30683879d9ad40f3228c56c012103aea0dfd576151cb399347aa6732f8fdf027b9ea3ea2e65fb754803f776e0a50900000000" ) { - errorMessage += 'created tx hex doesnt match; '; + errorMessage += "created tx hex doesnt match; "; isOk = false; } @@ -197,84 +239,96 @@ export default class Selftest extends Component { satoshiPerByte = Math.round(satoshiPerByte.toString(10)); if (satoshiPerByte !== 46) { - errorMessage += 'created tx satoshiPerByte doesnt match; '; + errorMessage += "created tx satoshiPerByte doesnt match; "; isOk = false; } // - let crypted = encryption.encrypt('data', 'password'); - let decrypted = encryption.decrypt(crypted, 'password'); + const crypted = encryption.encrypt("data", "password"); + const decrypted = encryption.decrypt(crypted, "password"); - if (decrypted !== 'data' && crypted && decrypted) { - errorMessage += 'encryption lib is not ok; '; + if (decrypted !== "data" && crypted && decrypted) { + errorMessage += "encryption lib is not ok; "; isOk = false; } // - let bip39 = require('bip39'); - let mnemonic = - 'honey risk juice trip orient galaxy win situate shoot anchor bounce remind horse traffic exotic since escape mimic ramp skin judge owner topple erode'; - let seed = bip39.mnemonicToSeed(mnemonic); - let root = bitcoin.bip32.fromSeed(seed); + const bip39 = require("bip39"); + const mnemonic = + "honey risk juice trip orient galaxy win situate shoot anchor bounce remind horse traffic exotic since escape mimic ramp skin judge owner topple erode"; + const seed = bip39.mnemonicToSeed(mnemonic); + const root = bitcoin.bip32.fromSeed(seed); - let path = "m/49'/0'/0'/0/0"; - let child = root.derivePath(path); - let address = bitcoin.payments.p2sh({ + const path = "m/49'/0'/0'/0/0"; + const child = root.derivePath(path); + const address = bitcoin.payments.p2sh({ redeem: bitcoin.payments.p2wpkh({ pubkey: child.publicKey, - network: bitcoin.networks.bitcoin, + network: bitcoin.networks.bitcoin }), - network: bitcoin.networks.bitcoin, + network: bitcoin.networks.bitcoin }).address; - if (address !== '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK') { - errorMessage += 'bip49 is not ok; '; + if (address !== "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK") { + errorMessage += "bip49 is not ok; "; isOk = false; } // - if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { - let hd = new HDSegwitP2SHWallet(); - let hashmap = {}; + if ( + typeof navigator !== "undefined" && + navigator.product === "ReactNative" + ) { + const hd = new HDSegwitP2SHWallet(); + const hashmap = {}; for (let c = 0; c < 1000; c++) { await hd.generate(); - let secret = hd.getSecret(); + const secret = hd.getSecret(); if (hashmap[secret]) { - throw new Error('Duplicate secret generated!'); + throw new Error("Duplicate secret generated!"); } hashmap[secret] = 1; - if (secret.split(' ').length !== 12 && secret.split(' ').length !== 24) { - throw new Error('mnemonic phrase not ok'); + if ( + secret.split(" ").length !== 12 && + secret.split(" ").length !== 24 + ) { + throw new Error("mnemonic phrase not ok"); } } - let hd2 = new HDSegwitP2SHWallet(); + const hd2 = new HDSegwitP2SHWallet(); hd2.setSecret(hd.getSecret()); if (!hd2.validateMnemonic()) { - throw new Error('mnemonic phrase validation not ok'); + throw new Error("mnemonic phrase validation not ok"); } // - let hd3 = new HDSegwitP2SHWallet(); - hd3._xpub = 'ypub6Wb82D7F38b48uzRVyTwydMCPcos4njzygPRCJ4x1enm6EA5YUthtWgJUPYiFTs7Sk53q8rJ9d1SJ2fBNqsyhjUTDR7gyF1SXbBnaa9xcQj'; + const hd3 = new HDSegwitP2SHWallet(); + hd3._xpub = + "ypub6Wb82D7F38b48uzRVyTwydMCPcos4njzygPRCJ4x1enm6EA5YUthtWgJUPYiFTs7Sk53q8rJ9d1SJ2fBNqsyhjUTDR7gyF1SXbBnaa9xcQj"; await hd3.fetchBalance(); - if (hd3.getBalance() !== 26000) throw new Error('Could not fetch HD balance'); + if (hd3.getBalance() !== 26000) + throw new Error("Could not fetch HD balance"); await hd3.fetchTransactions(); - if (hd3.transactions.length !== 1) throw new Error('Could not fetch HD transactions'); + if (hd3.transactions.length !== 1) + throw new Error("Could not fetch HD transactions"); // - let hd4 = new HDSegwitBech32Wallet(); - hd4._xpub = 'zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP'; + const hd4 = new HDSegwitBech32Wallet(); + hd4._xpub = + "zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP"; await hd4.fetchBalance(); - if (hd4.getBalance() !== 200000) throw new Error('Could not fetch HD Bech32 balance'); + if (hd4.getBalance() !== 200000) + throw new Error("Could not fetch HD Bech32 balance"); await hd4.fetchTransactions(); - if (hd4.getTransactions().length !== 4) throw new Error('Could not fetch HD Bech32 transactions'); + if (hd4.getTransactions().length !== 4) + throw new Error("Could not fetch HD Bech32 transactions"); } else { - console.warn('skipping RN-specific test'); + console.warn("skipping RN-specific test"); } // @@ -286,7 +340,7 @@ export default class Selftest extends Component { this.setState({ isLoading: false, isOk, - errorMessage, + errorMessage }); } @@ -296,7 +350,7 @@ export default class Selftest extends Component { } return ( - + @@ -304,13 +358,13 @@ export default class Selftest extends Component { {(() => { if (this.state.isOk) { return ( - + OK ); } else { return ( - + error: {this.state.errorMessage} @@ -328,6 +382,6 @@ export default class Selftest extends Component { Selftest.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/send/confirm.js b/screen/send/confirm.js index 7f5a1a59630..d90b71f0315 100644 --- a/screen/send/confirm.js +++ b/screen/send/confirm.js @@ -1,25 +1,39 @@ /* global alert */ -import React, { Component } from 'react'; -import { ActivityIndicator, FlatList, TouchableOpacity, StyleSheet, View } from 'react-native'; -import { Text } from 'react-native-elements'; -import { BlueButton, BlueText, SafeBlueArea, BlueCard, BlueSpacing40, BlueNavigationStyle } from '../../BlueComponents'; -import { BitcoinUnit } from '../../models/bitcoinUnits'; -import PropTypes from 'prop-types'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import Biometric from '../../class/biometrics'; -import { HDSegwitBech32Wallet } from '../../class'; -let loc = require('../../loc'); -let EV = require('../../events'); -let currency = require('../../currency'); -let BlueElectrum = require('../../BlueElectrum'); -let Bignumber = require('bignumber.js'); +import React, { Component } from "react"; +import { + ActivityIndicator, + FlatList, + TouchableOpacity, + StyleSheet, + View +} from "react-native"; +import { Text } from "react-native-elements"; +import { + BlueButton, + BlueText, + SafeBlueArea, + BlueCard, + BlueSpacing40, + BlueNavigationStyle +} from "../../BlueComponents"; +import { BitcoinUnit } from "../../models/bitcoinUnits"; +import PropTypes from "prop-types"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import Biometric from "../../class/biometrics"; +import { HDSegwitBech32Wallet } from "../../class"; + +const loc = require("../../loc"); +const EV = require("../../events"); +const currency = require("../../currency"); +const BlueElectrum = require("../../BlueElectrum"); +const Bignumber = require("bignumber.js"); /** @type {AppStorage} */ -const BlueApp = require('../../BlueApp'); +const BlueApp = require("../../BlueApp"); export default class Confirm extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(null, false), - title: loc.send.confirm.header, + title: loc.send.confirm.header }); constructor(props) { @@ -27,20 +41,22 @@ export default class Confirm extends Component { this.state = { isLoading: false, - fee: props.navigation.getParam('fee'), - feeSatoshi: new Bignumber(props.navigation.getParam('fee')).multipliedBy(100000000).toNumber(), - memo: props.navigation.getParam('memo'), - recipients: props.navigation.getParam('recipients'), - size: Math.round(props.navigation.getParam('tx').length / 2), - tx: props.navigation.getParam('tx'), - satoshiPerByte: props.navigation.getParam('satoshiPerByte'), - fromWallet: props.navigation.getParam('fromWallet'), + fee: props.navigation.getParam("fee"), + feeSatoshi: new Bignumber(props.navigation.getParam("fee")) + .multipliedBy(100000000) + .toNumber(), + memo: props.navigation.getParam("memo"), + recipients: props.navigation.getParam("recipients"), + size: Math.round(props.navigation.getParam("tx").length / 2), + tx: props.navigation.getParam("tx"), + satoshiPerByte: props.navigation.getParam("satoshiPerByte"), + fromWallet: props.navigation.getParam("fromWallet") }; } async componentDidMount() { - console.log('send/confirm - componentDidMount'); - console.log('address = ', this.state.recipients); + console.log("send/confirm - componentDidMount"); + console.log("address = ", this.state.recipients); this.isBiometricUseCapableAndEnabled = await Biometric.isBiometricUseCapableAndEnabled(); } @@ -56,14 +72,14 @@ export default class Confirm extends Component { } } - let result = await this.state.fromWallet.broadcastTx(this.state.tx); + const result = await this.state.fromWallet.broadcastTx(this.state.tx); if (result && result.code) { if (result.code === 1) { - const message = result.message.split('\n'); + const message = result.message.split("\n"); throw new Error(`${message[0]}: ${message[2]}`); } } else { - console.log('broadcast result = ', result); + console.log("broadcast result = ", result); EV(EV.enum.REMOTE_TRANSACTIONS_COUNT_CHANGED); // someone should fetch txs let amount = 0; const recipients = this.state.recipients; @@ -76,18 +92,24 @@ export default class Confirm extends Component { } if (this.state.fromWallet.type === HDSegwitBech32Wallet.type) { - amount = loc.formatBalanceWithoutSuffix(amount, BitcoinUnit.BTC, false); + amount = loc.formatBalanceWithoutSuffix( + amount, + BitcoinUnit.BTC, + false + ); } - this.props.navigation.navigate('Success', { + this.props.navigation.navigate("Success", { fee: Number(this.state.fee), amount, - dismissModal: () => this.props.navigation.dismiss(), + dismissModal: () => this.props.navigation.dismiss() }); this.setState({ isLoading: false }); } } catch (error) { - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); this.setState({ isLoading: false }); alert(error.message); } @@ -97,16 +119,18 @@ export default class Confirm extends Component { _renderItem = ({ index, item }) => { return ( <> - + {item.amount === BitcoinUnit.MAX - ? currency.satoshiToBTC(this.state.fromWallet.getBalance() - this.state.feeSatoshi) + ? currency.satoshiToBTC( + this.state.fromWallet.getBalance() - this.state.feeSatoshi + ) : item.amount || currency.satoshiToBTC(item.value)} - {' ' + BitcoinUnit.BTC} + {" " + BitcoinUnit.BTC} - {loc.send.create.to} + + {loc.send.create.to} + {item.address} {this.state.recipients.length > 1 && ( - + {index + 1} of {this.state.recipients.length} )} @@ -136,13 +168,27 @@ export default class Confirm extends Component { }; renderSeparator = () => { - return ; + return ( + + ); }; render() { return ( - + 1} extraData={this.state.recipients} @@ -150,27 +196,38 @@ export default class Confirm extends Component { renderItem={this._renderItem} keyExtractor={(_item, index) => `${index}`} ItemSeparatorComponent={this.renderSeparator} - style={{ maxHeight: '55%' }} + style={{ maxHeight: "55%" }} /> - + - {loc.send.create.fee}: {loc.formatBalance(this.state.feeSatoshi, BitcoinUnit.BTC)} + {loc.send.create.fee}:{" "} + {loc.formatBalance(this.state.feeSatoshi, BitcoinUnit.BTC)} {this.state.isLoading ? ( ) : ( - this.broadcast()} title={loc.send.confirm.sendNow} /> + this.broadcast()} + title={loc.send.confirm.sendNow} + /> )} - + {loc.transactions.details.transaction_details} @@ -208,16 +272,16 @@ export default class Confirm extends Component { const styles = StyleSheet.create({ transactionDetailsTitle: { color: BlueApp.settings.foregroundColor, - fontWeight: '500', + fontWeight: "500", fontSize: 17, - marginBottom: 2, + marginBottom: 2 }, transactionDetailsSubtitle: { color: BlueApp.settings.alternativeTextColor, - fontWeight: '500', + fontWeight: "500", fontSize: 15, - marginBottom: 20, - }, + marginBottom: 20 + } }); Confirm.propTypes = { @@ -234,9 +298,9 @@ Confirm.propTypes = { memo: PropTypes.string, fromWallet: PropTypes.shape({ fromAddress: PropTypes.string, - fromSecret: PropTypes.string, - }), - }), - }), - }), + fromSecret: PropTypes.string + }) + }) + }) + }) }; diff --git a/screen/send/create.js b/screen/send/create.js index d484850b3f9..dad951f93cf 100644 --- a/screen/send/create.js +++ b/screen/send/create.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { Component } from "react"; import { TextInput, FlatList, @@ -10,43 +10,48 @@ import { TouchableWithoutFeedback, Keyboard, Text, - View, -} from 'react-native'; -import { BlueNavigationStyle, SafeBlueArea, BlueCard, BlueText } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import Privacy from '../../Privacy'; -import { BitcoinUnit } from '../../models/bitcoinUnits'; + View +} from "react-native"; +import { + BlueNavigationStyle, + SafeBlueArea, + BlueCard, + BlueText +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import Privacy from "../../Privacy"; +import { BitcoinUnit } from "../../models/bitcoinUnits"; /** @type {AppStorage} */ -const BlueApp = require('../../BlueApp'); -const loc = require('../../loc'); -const currency = require('../../currency'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); +const currency = require("../../currency"); export default class SendCreate extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle, - title: loc.send.create.details, + title: loc.send.create.details }); constructor(props) { super(props); - console.log('send/create constructor'); + console.log("send/create constructor"); this.state = { isLoading: false, - fee: props.navigation.getParam('fee'), - recipients: props.navigation.getParam('recipients'), - memo: props.navigation.getParam('memo') || '', - size: Math.round(props.navigation.getParam('tx').length / 2), - tx: props.navigation.getParam('tx'), - satoshiPerByte: props.navigation.getParam('satoshiPerByte'), - wallet: props.navigation.getParam('wallet'), - feeSatoshi: props.navigation.getParam('feeSatoshi'), + fee: props.navigation.getParam("fee"), + recipients: props.navigation.getParam("recipients"), + memo: props.navigation.getParam("memo") || "", + size: Math.round(props.navigation.getParam("tx").length / 2), + tx: props.navigation.getParam("tx"), + satoshiPerByte: props.navigation.getParam("satoshiPerByte"), + wallet: props.navigation.getParam("wallet"), + feeSatoshi: props.navigation.getParam("feeSatoshi") }; } async componentDidMount() { Privacy.enableBlur(); - console.log('send/create - componentDidMount'); + console.log("send/create - componentDidMount"); } componentWillUnmount() { @@ -57,17 +62,22 @@ export default class SendCreate extends Component { return ( <> - {loc.send.create.to} + + {loc.send.create.to} + {item.address} - {loc.send.create.amount} + + {loc.send.create.amount} + {item.amount === BitcoinUnit.MAX - ? currency.satoshiToBTC(this.state.wallet.getBalance()) - this.state.fee - : item.amount || currency.satoshiToBTC(item.value)}{' '} + ? currency.satoshiToBTC(this.state.wallet.getBalance()) - + this.state.fee + : item.amount || currency.satoshiToBTC(item.value)}{" "} {BitcoinUnit.BTC} {this.state.recipients.length > 1 && ( - + {index + 1} of {this.state.recipients.length} )} @@ -77,7 +87,15 @@ export default class SendCreate extends Component { }; renderSeparator = () => { - return ; + return ( + + ); }; render() { @@ -85,20 +103,22 @@ export default class SendCreate extends Component { - - {loc.send.create.this_is_hex} + + + {loc.send.create.this_is_hex} + - Clipboard.setString(this.state.tx)}> - Copy and broadcast later + Clipboard.setString(this.state.tx)} + > + + Copy and broadcast later + - Linking.openURL('https://wallet.veles.network/?verify=' + this.state.tx)}> - Verify on Veles Webwallet + + Linking.openURL( + "https://wallet.veles.network/?verify=" + this.state.tx + ) + } + > + + Verify on Veles Webwallet + @@ -122,20 +170,34 @@ export default class SendCreate extends Component { keyExtractor={(_item, index) => `${index}`} ItemSeparatorComponent={this.renderSeparator} /> - {loc.send.create.fee} + + {loc.send.create.fee} + {this.state.fee} {BitcoinUnit.BTC} - {loc.send.create.tx_size} - {this.state.size} bytes + + {loc.send.create.tx_size} + + + {this.state.size} bytes + - {loc.send.create.satoshi_per_byte} - {this.state.satoshiPerByte} Sat/B + + {loc.send.create.satoshi_per_byte} + + + {this.state.satoshiPerByte} Sat/B + {this.state.memo.length > 0 && ( <> - {loc.send.create.memo} - {this.state.memo} + + {loc.send.create.memo} + + + {this.state.memo} + )} @@ -148,17 +210,17 @@ export default class SendCreate extends Component { const styles = StyleSheet.create({ transactionDetailsTitle: { - color: '#ffffff', - fontWeight: '500', + color: "#ffffff", + fontWeight: "500", fontSize: 17, - marginBottom: 2, + marginBottom: 2 }, transactionDetailsSubtitle: { - color: '#9aa0aa', - fontWeight: '500', + color: "#9aa0aa", + fontWeight: "500", fontSize: 15, - marginBottom: 20, - }, + marginBottom: 20 + } }); SendCreate.propTypes = { @@ -172,8 +234,8 @@ SendCreate.propTypes = { amount: PropTypes.string, fee: PropTypes.number, address: PropTypes.string, - memo: PropTypes.string, - }), - }), - }), + memo: PropTypes.string + }) + }) + }) }; diff --git a/screen/send/details.js b/screen/send/details.js index 984c82706cf..7f1ca54e4d9 100644 --- a/screen/send/details.js +++ b/screen/send/details.js @@ -1,5 +1,5 @@ /* global alert */ -import React, { Component } from 'react'; +import React, { Component } from "react"; import { ActivityIndicator, View, @@ -14,10 +14,10 @@ import { Dimensions, Platform, ScrollView, - Text, -} from 'react-native'; -import { Icon } from 'react-native-elements'; -import AsyncStorage from '@react-native-community/async-storage'; + Text +} from "react-native"; +import { Icon } from "react-native-elements"; +import AsyncStorage from "@react-native-community/async-storage"; import { BlueCreateTxNavigationStyle, BlueButton, @@ -27,24 +27,33 @@ import { BlueLoading, BlueUseAllFundsButton, BlueListItem, - BlueText, -} from '../../BlueComponents'; -import Slider from '@react-native-community/slider'; -import PropTypes from 'prop-types'; -import Modal from 'react-native-modal'; -import NetworkTransactionFees, { NetworkTransactionFee } from '../../models/networkTransactionFees'; -import BitcoinBIP70TransactionDecode from '../../bip70/bip70'; -import { BitcoinUnit, Chain } from '../../models/bitcoinUnits'; -import { HDLegacyP2PKHWallet, HDSegwitBech32Wallet, HDSegwitP2SHWallet, WatchOnlyWallet } from '../../class'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import { BitcoinTransaction } from '../../models/bitcoinTransactionInfo'; -const bitcoin = require('bitcoinjs-lib'); -const bip21 = require('bip21'); -let BigNumber = require('bignumber.js'); -const { width } = Dimensions.get('window'); + BlueText +} from "../../BlueComponents"; +import Slider from "@react-native-community/slider"; +import PropTypes from "prop-types"; +import Modal from "react-native-modal"; +import NetworkTransactionFees, { + NetworkTransactionFee +} from "../../models/networkTransactionFees"; +import BitcoinBIP70TransactionDecode from "../../bip70/bip70"; +import { BitcoinUnit, Chain } from "../../models/bitcoinUnits"; +import { + HDLegacyP2PKHWallet, + HDSegwitBech32Wallet, + HDSegwitP2SHWallet, + WatchOnlyWallet +} from "../../class"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import { BitcoinTransaction } from "../../models/bitcoinTransactionInfo"; + +const bitcoin = require("bitcoinjs-lib"); +const bip21 = require("bip21"); +let BigNumber = require("bignumber.js"); + +const { width } = Dimensions.get("window"); /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); +let BlueApp = require("../../BlueApp"); +let loc = require("../../loc"); const btcAddressRx = /^[a-zA-Z0-9]{26,35}$/; @@ -53,25 +62,30 @@ export default class SendDetails extends Component { ...BlueCreateTxNavigationStyle( navigation, navigation.state.params.withAdvancedOptionsMenuButton, - navigation.state.params.advancedOptionsMenuButtonAction, + navigation.state.params.advancedOptionsMenuButtonAction ), - title: loc.send.header, + title: loc.send.header }); constructor(props) { super(props); let fromAddress; - if (props.navigation.state.params) fromAddress = props.navigation.state.params.fromAddress; + if (props.navigation.state.params) + fromAddress = props.navigation.state.params.fromAddress; let fromSecret; - if (props.navigation.state.params) fromSecret = props.navigation.state.params.fromSecret; + if (props.navigation.state.params) + fromSecret = props.navigation.state.params.fromSecret; let fromWallet = null; - if (props.navigation.state.params) fromWallet = props.navigation.state.params.fromWallet; + if (props.navigation.state.params) + fromWallet = props.navigation.state.params.fromWallet; const wallets = BlueApp.getWallets(); if (wallets.length === 0) { - alert('Before creating a transaction, you must first add a Veles wallet.'); + alert( + "Before creating a transaction, you must first add a Veles wallet." + ); return props.navigation.goBack(null); } else { if (!fromWallet && wallets.length > 0) { @@ -89,23 +103,25 @@ export default class SendDetails extends Component { fromWallet, fromSecret, addresses: [], - memo: '', + memo: "", networkTransactionFees: new NetworkTransactionFee(1, 1, 1), fee: 1, feeSliderValue: 1, bip70TransactionExpiration: null, - renderWalletSelectionButtonHidden: false, + renderWalletSelectionButtonHidden: false }; } } renderNavigationHeader() { this.props.navigation.setParams({ - withAdvancedOptionsMenuButton: this.state.fromWallet.allowBatchSend() || this.state.fromWallet.allowSendMax(), + withAdvancedOptionsMenuButton: + this.state.fromWallet.allowBatchSend() || + this.state.fromWallet.allowSendMax(), advancedOptionsMenuButtonAction: () => { Keyboard.dismiss(); this.setState({ isAdvancedTransactionOptionsVisible: true }); - }, + } }); } @@ -124,30 +140,38 @@ export default class SendDetails extends Component { feeSliderValue: bip70.feeSliderValue, fee: bip70.fee, isLoading: false, - bip70TransactionExpiration: bip70.bip70TransactionExpiration, + bip70TransactionExpiration: bip70.bip70TransactionExpiration }); } else { let recipients = this.state.addresses; - const dataWithoutSchema = data.replace('veles:', ''); - if (btcAddressRx.test(dataWithoutSchema) || (dataWithoutSchema.indexOf('veles1') === 0 && dataWithoutSchema.indexOf('?') === -1)) { - recipients[[this.state.recipientsScrollIndex]].address = dataWithoutSchema; + const dataWithoutSchema = data.replace("veles:", ""); + if ( + btcAddressRx.test(dataWithoutSchema) || + (dataWithoutSchema.indexOf("veles1") === 0 && + dataWithoutSchema.indexOf("?") === -1) + ) { + recipients[ + [this.state.recipientsScrollIndex] + ].address = dataWithoutSchema; this.setState({ address: recipients, bip70TransactionExpiration: null, - isLoading: false, + isLoading: false }); } else { - let address = ''; + let address = ""; let options; try { - if (!data.toLowerCase().startsWith('veles:')) { + if (!data.toLowerCase().startsWith("veles:")) { data = `veles:${data}`; } const decoded = bip21.decode(data); address = decoded.address; options = decoded.options; } catch (error) { - data = data.replace(/(amount)=([^&]+)/g, '').replace(/(amount)=([^&]+)&/g, ''); + data = data + .replace(/(amount)=([^&]+)/g, "") + .replace(/(amount)=([^&]+)&/g, ""); const decoded = bip21.decode(data); decoded.options.amount = 0; address = decoded.address; @@ -155,14 +179,15 @@ export default class SendDetails extends Component { this.setState({ isLoading: false }); } console.log(options); - if (btcAddressRx.test(address) || address.indexOf('veles1') === 0) { + if (btcAddressRx.test(address) || address.indexOf("veles1") === 0) { recipients[[this.state.recipientsScrollIndex]].address = address; - recipients[[this.state.recipientsScrollIndex]].amount = options.amount; + recipients[[this.state.recipientsScrollIndex]].amount = + options.amount; this.setState({ addresses: recipients, memo: options.label || options.message, bip70TransactionExpiration: null, - isLoading: false, + isLoading: false }); } else { this.setState({ isLoading: false }); @@ -174,20 +199,37 @@ export default class SendDetails extends Component { async componentDidMount() { this.renderNavigationHeader(); - console.log('send/details - componentDidMount'); - StatusBar.setBarStyle('dark-content'); - this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow); - this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide); + console.log("send/details - componentDidMount"); + StatusBar.setBarStyle("dark-content"); + this.keyboardDidShowListener = Keyboard.addListener( + "keyboardDidShow", + this._keyboardDidShow + ); + this.keyboardDidHideListener = Keyboard.addListener( + "keyboardDidHide", + this._keyboardDidHide + ); let addresses = []; - let initialMemo = ''; + let initialMemo = ""; if (this.props.navigation.state.params.uri) { const uri = this.props.navigation.state.params.uri; if (BitcoinBIP70TransactionDecode.matchesPaymentURL(uri)) { - const { recipient, memo, fee, feeSliderValue } = await this.processBIP70Invoice(uri); + const { + recipient, + memo, + fee, + feeSliderValue + } = await this.processBIP70Invoice(uri); addresses.push(recipient); initialMemo = memo; - this.setState({ addresses, memo: initialMemo, fee, feeSliderValue, isLoading: false }); + this.setState({ + addresses, + memo: initialMemo, + fee, + feeSliderValue, + isLoading: false + }); } else { try { const { address, amount, memo } = this.decodeBitcoinUri(uri); @@ -196,50 +238,70 @@ export default class SendDetails extends Component { this.setState({ addresses, memo: initialMemo, isLoading: false }); } catch (error) { console.log(error); - alert('Error: Unable to decode Veles address'); + alert("Error: Unable to decode Veles address"); } } } else if (this.props.navigation.state.params.address) { - addresses.push(new BitcoinTransaction(this.props.navigation.state.params.address)); - if (this.props.navigation.state.params.memo) initialMemo = this.props.navigation.state.params.memo; + addresses.push( + new BitcoinTransaction(this.props.navigation.state.params.address) + ); + if (this.props.navigation.state.params.memo) + initialMemo = this.props.navigation.state.params.memo; this.setState({ addresses, memo: initialMemo, isLoading: false }); } else { - this.setState({ addresses: [new BitcoinTransaction()], isLoading: false }); + this.setState({ + addresses: [new BitcoinTransaction()], + isLoading: false + }); } try { - const cachedNetworkTransactionFees = JSON.parse(await AsyncStorage.getItem(NetworkTransactionFee.StorageKey)); + const cachedNetworkTransactionFees = JSON.parse( + await AsyncStorage.getItem(NetworkTransactionFee.StorageKey) + ); - if (cachedNetworkTransactionFees && cachedNetworkTransactionFees.hasOwnProperty('halfHourFee')) { + if ( + cachedNetworkTransactionFees && + cachedNetworkTransactionFees.hasOwnProperty("halfHourFee") + ) { this.setState({ fee: cachedNetworkTransactionFees.fastestFee, networkTransactionFees: cachedNetworkTransactionFees, - feeSliderValue: cachedNetworkTransactionFees.fastestFee, + feeSliderValue: cachedNetworkTransactionFees.fastestFee }); } } catch (_) {} try { let recommendedFees = await NetworkTransactionFees.recommendedFees(); - if (recommendedFees && recommendedFees.hasOwnProperty('fastestFee')) { - await AsyncStorage.setItem(NetworkTransactionFee.StorageKey, JSON.stringify(recommendedFees)); + if (recommendedFees && recommendedFees.hasOwnProperty("fastestFee")) { + await AsyncStorage.setItem( + NetworkTransactionFee.StorageKey, + JSON.stringify(recommendedFees) + ); this.setState({ fee: recommendedFees.fastestFee, networkTransactionFees: recommendedFees, - feeSliderValue: recommendedFees.fastestFee, + feeSliderValue: recommendedFees.fastestFee }); if (this.props.navigation.state.params.uri) { - if (BitcoinBIP70TransactionDecode.matchesPaymentURL(this.props.navigation.state.params.uri)) { + if ( + BitcoinBIP70TransactionDecode.matchesPaymentURL( + this.props.navigation.state.params.uri + ) + ) { this.processBIP70Invoice(this.props.navigation.state.params.uri); } else { try { - const { address, amount, memo } = this.decodeBitcoinUri(this.props.navigation.getParam('uri')); + const { address, amount, memo } = this.decodeBitcoinUri( + this.props.navigation.getParam("uri") + ); this.setState({ address, amount, memo, isLoading: false }); } catch (error) { console.log(error); this.setState({ isLoading: false }); - alert('Error: Unable to decode Veles address'); + alert("Error: Unable to decode Veles address"); } } } @@ -263,19 +325,21 @@ export default class SendDetails extends Component { }; decodeBitcoinUri(uri) { - let amount = ''; + let amount = ""; let parsedBitcoinUri = null; - let address = uri || ''; - let memo = ''; + let address = uri || ""; + let memo = ""; try { parsedBitcoinUri = bip21.decode(uri); - address = parsedBitcoinUri.hasOwnProperty('address') ? parsedBitcoinUri.address : address; - if (parsedBitcoinUri.hasOwnProperty('options')) { - if (parsedBitcoinUri.options.hasOwnProperty('amount')) { + address = parsedBitcoinUri.hasOwnProperty("address") + ? parsedBitcoinUri.address + : address; + if (parsedBitcoinUri.hasOwnProperty("options")) { + if (parsedBitcoinUri.options.hasOwnProperty("amount")) { amount = parsedBitcoinUri.options.amount.toString(); amount = parsedBitcoinUri.options.amount; } - if (parsedBitcoinUri.options.hasOwnProperty('label')) { + if (parsedBitcoinUri.options.hasOwnProperty("label")) { memo = parsedBitcoinUri.options.label || memo; } } @@ -297,7 +361,7 @@ export default class SendDetails extends Component { return balance; } - return (availableBalance === 'NaN' && balance) || availableBalance; + return (availableBalance === "NaN" && balance) || availableBalance; } calculateFee(utxos, txhex, utxoIsInSatoshis) { @@ -306,7 +370,9 @@ export default class SendDetails extends Component { index[0] = 0; for (let utxo of utxos) { if (!utxoIsInSatoshis) { - utxo.value = new BigNumber(utxo.value).multipliedBy(100000000).toNumber(); + utxo.value = new BigNumber(utxo.value) + .multipliedBy(100000000) + .toNumber(); } index[c] = utxo.value + index[c - 1]; c++; @@ -323,7 +389,9 @@ export default class SendDetails extends Component { totalOutput += o.value * 1; } - return new BigNumber(totalInput - totalOutput).dividedBy(100000000).toNumber(); + return new BigNumber(totalInput - totalOutput) + .dividedBy(100000000) + .toNumber(); } async processBIP70Invoice(text) { @@ -334,14 +402,18 @@ export default class SendDetails extends Component { .then(response => { const recipient = new BitcoinTransaction( response.address, - loc.formatBalanceWithoutSuffix(response.amount, BitcoinUnit.BTC, false), + loc.formatBalanceWithoutSuffix( + response.amount, + BitcoinUnit.BTC, + false + ) ); return { recipient, memo: response.memo, fee: response.fee, feeSliderValue: response.fee, - bip70TransactionExpiration: response.expires, + bip70TransactionExpiration: response.expires }; }) .catch(error => { @@ -352,37 +424,55 @@ export default class SendDetails extends Component { } catch (error) { return false; } - throw new Error('BIP70: Unable to process.'); + throw new Error("BIP70: Unable to process."); } async createTransaction() { Keyboard.dismiss(); this.setState({ isLoading: true }); let error = false; - let requestedSatPerByte = this.state.fee.toString().replace(/\D/g, ''); + let requestedSatPerByte = this.state.fee.toString().replace(/\D/g, ""); for (const [index, transaction] of this.state.addresses.entries()) { - if (!transaction.amount || transaction.amount < 0 || parseFloat(transaction.amount) === 0) { + if ( + !transaction.amount || + transaction.amount < 0 || + parseFloat(transaction.amount) === 0 + ) { error = loc.send.details.amount_field_is_not_valid; - console.log('validation error'); - } else if (!this.state.fee || !requestedSatPerByte || parseFloat(requestedSatPerByte) < 1) { + console.log("validation error"); + } else if ( + !this.state.fee || + !requestedSatPerByte || + parseFloat(requestedSatPerByte) < 1 + ) { error = loc.send.details.fee_field_is_not_valid; - console.log('validation error'); + console.log("validation error"); } else if (!transaction.address) { error = loc.send.details.address_field_is_not_valid; - console.log('validation error'); - } else if (this.recalculateAvailableBalance(this.state.fromWallet.getBalance(), transaction.amount, 0) < 0) { + console.log("validation error"); + } else if ( + this.recalculateAvailableBalance( + this.state.fromWallet.getBalance(), + transaction.amount, + 0 + ) < 0 + ) { // first sanity check is that sending amount is not bigger than available balance error = loc.send.details.total_exceeds_balance; - console.log('validation error'); - } else if (BitcoinBIP70TransactionDecode.isExpired(this.state.bip70TransactionExpiration)) { - error = 'Transaction has expired.'; - console.log('validation error'); + console.log("validation error"); + } else if ( + BitcoinBIP70TransactionDecode.isExpired( + this.state.bip70TransactionExpiration + ) + ) { + error = "Transaction has expired."; + console.log("validation error"); } else if (transaction.address) { const address = transaction.address.trim().toLowerCase(); - if (address.startsWith('lnb') || address.startsWith('lightning:lnb')) { + if (address.startsWith("lnb") || address.startsWith("lightning:lnb")) { error = - 'This address appears to be for a Lightning invoice. Please, go to your Lightning wallet in order to make a payment for this invoice.'; - console.log('validation error'); + "This address appears to be for a Lightning invoice. Please, go to your Lightning wallet in order to make a payment for this invoice."; + console.log("validation error"); } } @@ -390,7 +480,7 @@ export default class SendDetails extends Component { try { bitcoin.address.toOutputScript(transaction.address); } catch (err) { - console.log('validation error'); + console.log("validation error"); console.log(err); error = loc.send.details.address_field_is_not_valid; } @@ -406,7 +496,9 @@ export default class SendDetails extends Component { } this.setState({ isLoading: false, recipientsScrollIndex: index }); alert(error); - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); break; } } @@ -415,14 +507,19 @@ export default class SendDetails extends Component { return; } - if (this.state.fromWallet.type === HDSegwitBech32Wallet.type || this.state.fromWallet.type === WatchOnlyWallet.type) { + if ( + this.state.fromWallet.type === HDSegwitBech32Wallet.type || + this.state.fromWallet.type === WatchOnlyWallet.type + ) { // new send is supported by BIP84 or watchonly with HW wallet support (it uses BIP84 under the hood anyway) try { await this.createHDBech32Transaction(); } catch (Err) { this.setState({ isLoading: false }, () => { alert(Err.message); - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); }); } return; @@ -441,29 +538,46 @@ export default class SendDetails extends Component { await this.state.fromWallet.fetchUtxo(); utxo = this.state.fromWallet.utxo; do { - console.log('try #', tries, 'fee=', fee); - if (this.recalculateAvailableBalance(this.state.fromWallet.getBalance(), firstTransaction.amount, fee) < 0) { + console.log("try #", tries, "fee=", fee); + if ( + this.recalculateAvailableBalance( + this.state.fromWallet.getBalance(), + firstTransaction.amount, + fee + ) < 0 + ) { // we could not add any fee. user is trying to send all he's got. that wont work throw new Error(loc.send.details.total_exceeds_balance); } let startTime = Date.now(); - tx = this.state.fromWallet.createTx(utxo, firstTransaction.amount, fee, firstTransaction.address, this.state.memo); + tx = this.state.fromWallet.createTx( + utxo, + firstTransaction.amount, + fee, + firstTransaction.address, + this.state.memo + ); let endTime = Date.now(); - console.log('create tx ', (endTime - startTime) / 1000, 'sec'); + console.log("create tx ", (endTime - startTime) / 1000, "sec"); let txDecoded = bitcoin.Transaction.fromHex(tx); txid = txDecoded.getId(); - console.log('txid', txid); - console.log('txhex', tx); + console.log("txid", txid); + console.log("txhex", tx); let feeSatoshi = new BigNumber(fee).multipliedBy(100000000); - actualSatoshiPerByte = feeSatoshi.dividedBy(Math.round(tx.length / 2)); + actualSatoshiPerByte = feeSatoshi.dividedBy( + Math.round(tx.length / 2) + ); actualSatoshiPerByte = actualSatoshiPerByte.toNumber(); console.log({ satoshiPerByte: actualSatoshiPerByte }); - if (Math.round(actualSatoshiPerByte) !== requestedSatPerByte * 1 || Math.floor(actualSatoshiPerByte) < 1) { - console.log('fee is not correct, retrying'); + if ( + Math.round(actualSatoshiPerByte) !== requestedSatPerByte * 1 || + Math.floor(actualSatoshiPerByte) < 1 + ) { + console.log("fee is not correct, retrying"); fee = feeSatoshi .multipliedBy(requestedSatPerByte / actualSatoshiPerByte) .plus(10) @@ -477,31 +591,34 @@ export default class SendDetails extends Component { BlueApp.tx_metadata = BlueApp.tx_metadata || {}; BlueApp.tx_metadata[txid] = { txhex: tx, - memo: this.state.memo, + memo: this.state.memo }; await BlueApp.saveToDisk(); } catch (err) { console.log(err); - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); alert(err); this.setState({ isLoading: false }); return; } this.setState({ isLoading: false }, () => - this.props.navigation.navigate('Confirm', { + this.props.navigation.navigate("Confirm", { recipients: [firstTransaction], // HD wallet's utxo is in sats, classic segwit wallet utxos are in btc fee: this.calculateFee( utxo, tx, - this.state.fromWallet.type === HDSegwitP2SHWallet.type || this.state.fromWallet.type === HDLegacyP2PKHWallet.type, + this.state.fromWallet.type === HDSegwitP2SHWallet.type || + this.state.fromWallet.type === HDLegacyP2PKHWallet.type ), memo: this.state.memo, fromWallet: this.state.fromWallet, tx: tx, - satoshiPerByte: actualSatoshiPerByte.toFixed(2), - }), + satoshiPerByte: actualSatoshiPerByte.toFixed(2) + }) ); }); } @@ -512,14 +629,20 @@ export default class SendDetails extends Component { await wallet.fetchUtxo(); const firstTransaction = this.state.addresses[0]; const changeAddress = await wallet.getAddressForTransaction(); - let satoshis = new BigNumber(firstTransaction.amount).multipliedBy(100000000).toNumber(); - const requestedSatPerByte = +this.state.fee.toString().replace(/\D/g, ''); + let satoshis = new BigNumber(firstTransaction.amount) + .multipliedBy(100000000) + .toNumber(); + const requestedSatPerByte = +this.state.fee.toString().replace(/\D/g, ""); console.log({ satoshis, requestedSatPerByte, utxo: wallet.getUtxo() }); let targets = []; for (const transaction of this.state.addresses) { const amount = - transaction.amount === BitcoinUnit.MAX ? BitcoinUnit.MAX : new BigNumber(transaction.amount).multipliedBy(100000000).toNumber(); + transaction.amount === BitcoinUnit.MAX + ? BitcoinUnit.MAX + : new BigNumber(transaction.amount) + .multipliedBy(100000000) + .toNumber(); if (amount > 0.0 || amount === BitcoinUnit.MAX) { targets.push({ address: transaction.address, value: amount }); console.warn("createHDbech: " + transaction.address, amount); @@ -527,10 +650,17 @@ export default class SendDetails extends Component { } if (firstTransaction.amount === BitcoinUnit.MAX) { - targets = [{ address: firstTransaction.address, amount: BitcoinUnit.MAX }]; + targets = [ + { address: firstTransaction.address, amount: BitcoinUnit.MAX } + ]; } - let { tx, fee, psbt } = wallet.createTransaction(wallet.getUtxo(), targets, requestedSatPerByte, changeAddress); + let { tx, fee, psbt } = wallet.createTransaction( + wallet.getUtxo(), + targets, + requestedSatPerByte, + changeAddress + ); if (wallet.type === WatchOnlyWallet.type) { // watch-only wallets with enabled HW wallet support have different flow. we have to show PSBT to user as QR code @@ -538,11 +668,11 @@ export default class SendDetails extends Component { // user whether he wants to broadcast it this.setState({ isLoading: false }, () => - this.props.navigation.navigate('PsbtWithHardwareWallet', { + this.props.navigation.navigate("PsbtWithHardwareWallet", { memo: this.state.memo, fromWallet: wallet, - psbt, - }), + psbt + }) ); return; } @@ -550,32 +680,39 @@ export default class SendDetails extends Component { BlueApp.tx_metadata = BlueApp.tx_metadata || {}; BlueApp.tx_metadata[tx.getId()] = { txhex: tx.toHex(), - memo: this.state.memo, + memo: this.state.memo }; await BlueApp.saveToDisk(); this.setState({ isLoading: false }, () => - this.props.navigation.navigate('Confirm', { + this.props.navigation.navigate("Confirm", { fee: new BigNumber(fee).dividedBy(100000000).toNumber(), memo: this.state.memo, fromWallet: wallet, tx: tx.toHex(), recipients: targets, - satoshiPerByte: requestedSatPerByte, - }), + satoshiPerByte: requestedSatPerByte + }) ); } onWalletSelect = wallet => { const changeWallet = () => { - this.setState({ fromAddress: wallet.getAddress(), fromSecret: wallet.getSecret(), fromWallet: wallet }, () => { - this.renderNavigationHeader(); - this.props.navigation.pop(); - }); + this.setState( + { + fromAddress: wallet.getAddress(), + fromSecret: wallet.getSecret(), + fromWallet: wallet + }, + () => { + this.renderNavigationHeader(); + this.props.navigation.pop(); + }); + ); }; if (this.state.addresses.length > 1 && !wallet.allowBatchSend()) { - ReactNativeHapticFeedback.trigger('notificationWarning'); + ReactNativeHapticFeedback.trigger("notificationWarning"); Alert.alert( - 'Wallet Selection', + "Wallet Selection", `The selected wallet does not support sending Veles to multiple recipients. Are you sure to want to select this wallet?`, [ { @@ -583,21 +720,31 @@ export default class SendDetails extends Component { onPress: async () => { const firstTransaction = this.state.addresses.find(element => { - const feeSatoshi = new BigNumber(element.amount).multipliedBy(100000000); + const feeSatoshi = new BigNumber(element.amount).multipliedBy( + 100000000 + ); return element.address.length > 0 && feeSatoshi > 0; }) || this.state.addresses[0]; - this.setState({ addresses: [firstTransaction], recipientsScrollIndex: 0 }, () => changeWallet()); + this.setState( + { addresses: [firstTransaction], recipientsScrollIndex: 0 }, + () => changeWallet() + ); }, - style: 'default', + style: "default" }, - { text: loc.send.details.cancel, onPress: () => {}, style: 'cancel' }, + { text: loc.send.details.cancel, onPress: () => {}, style: "cancel" } ], - { cancelable: false }, + { cancelable: false } ); - } else if (this.state.addresses.some(element => element.amount === BitcoinUnit.MAX) && !wallet.allowSendMax()) { - ReactNativeHapticFeedback.trigger('notificationWarning'); + } else if ( + this.state.addresses.some( + element => element.amount === BitcoinUnit.MAX + ) && + !wallet.allowSendMax() + ) { + ReactNativeHapticFeedback.trigger("notificationWarning"); Alert.alert( - 'Wallet Selection', + "Wallet Selection", `The selected wallet does not support automatic maximum balance calculation. Are you sure to want to select this wallet?`, [ { @@ -608,13 +755,16 @@ export default class SendDetails extends Component { return element.amount === BitcoinUnit.MAX; }) || this.state.addresses[0]; firstTransaction.amount = 0; - this.setState({ addresses: [firstTransaction], recipientsScrollIndex: 0 }, () => changeWallet()); + this.setState( + { addresses: [firstTransaction], recipientsScrollIndex: 0 }, + () => changeWallet() + ); }, - style: 'default', + style: "default" }, - { text: loc.send.details.cancel, onPress: () => {}, style: 'cancel' }, + { text: loc.send.details.cancel, onPress: () => {}, style: "cancel" } ], - { cancelable: false }, + { cancelable: false } ); } else { changeWallet(); @@ -634,9 +784,14 @@ export default class SendDetails extends Component { this.setState({ isFeeSelectionModalVisible: false }); }} > - + - this.textInput.focus()}> + this.textInput.focus()} + > { @@ -645,48 +800,95 @@ export default class SendDetails extends Component { value={this.state.fee.toString()} onEndEditing={() => { if (this.state.fee < 1 || this.state.feeSliderValue < 1) { - this.setState({ fee: Number(1), feeSliderValue: Number(1) }); + this.setState({ + fee: Number(1), + feeSliderValue: Number(1) + }); } }} onChangeText={value => { - let newValue = value.replace(/\D/g, ''); - this.setState({ fee: newValue, feeSliderValue: Number(newValue) }); + let newValue = value.replace(/\D/g, ""); + this.setState({ + fee: newValue, + feeSliderValue: Number(newValue) + }); }} maxLength={9} editable={!this.state.isLoading} placeholderTextColor="#37c0a1" placeholder={this.state.networkTransactionFees.halfHourFee.toString()} - style={{ fontWeight: '600', color: '#37c0a1', marginBottom: 0, marginRight: 4, textAlign: 'right', fontSize: 36 }} - inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} + style={{ + fontWeight: "600", + color: "#37c0a1", + marginBottom: 0, + marginRight: 4, + textAlign: "right", + fontSize: 36 + }} + inputAccessoryViewID={ + BlueDismissKeyboardInputAccessory.InputAccessoryViewID + } /> sat/b {this.state.networkTransactionFees.fastestFee > 1 && ( - + this.setState({ feeSliderValue: value.toFixed(0), fee: value.toFixed(0) })} + onValueChange={value => + this.setState({ + feeSliderValue: value.toFixed(0), + fee: value.toFixed(0) + }) + } minimumValue={1} - maximumValue={Number(this.state.networkTransactionFees.fastestFee)} + maximumValue={Number( + this.state.networkTransactionFees.fastestFee + )} value={Number(this.state.feeSliderValue)} maximumTrackTintColor="#d8d8d8" minimumTrackTintColor="#37c0a1" style={{ flex: 1 }} /> - - slow - fast + + + slow + + + fast + )} @@ -697,7 +899,9 @@ export default class SendDetails extends Component { }; renderAdvancedTransactionOptionsModal = () => { - const isSendMaxUsed = this.state.addresses.some(element => element.amount === BitcoinUnit.MAX); + const isSendMaxUsed = this.state.addresses.some( + element => element.amount === BitcoinUnit.MAX + ); return ( - + {this.state.fromWallet.allowSendMax() && ( 0) || isSendMaxUsed} + disabled={ + !(this.state.fromWallet.getBalance() > 0) || isSendMaxUsed + } title="Use Full Balance" hideChevron component={TouchableOpacity} @@ -731,12 +939,13 @@ export default class SendDetails extends Component { this.setState( { addresses, - isAdvancedTransactionOptionsVisible: false, + isAdvancedTransactionOptionsVisible: false }, () => { this.scrollView.scrollToEnd(); - if (this.state.addresses.length > 1) this.scrollView.flashScrollIndicators(); - }, + if (this.state.addresses.length > 1) + this.scrollView.flashScrollIndicators(); + } ); }} /> @@ -751,12 +960,15 @@ export default class SendDetails extends Component { this.setState( { addresses, - isAdvancedTransactionOptionsVisible: false, + isAdvancedTransactionOptionsVisible: false }, () => { - if (this.state.addresses.length > 1) this.scrollView.flashScrollIndicators(); - this.setState({ recipientsScrollIndex: this.scrollViewCurrentIndex }); - }, + if (this.state.addresses.length > 1) + this.scrollView.flashScrollIndicators(); + this.setState({ + recipientsScrollIndex: this.scrollViewCurrentIndex + }); + } ); }} /> @@ -770,8 +982,20 @@ export default class SendDetails extends Component { renderCreateButton = () => { return ( - - {this.state.isLoading ? : this.createTransaction()} title={'Next'} />} + + {this.state.isLoading ? ( + + ) : ( + this.createTransaction()} title={"Next"} /> + )} ); }; @@ -779,26 +1003,52 @@ export default class SendDetails extends Component { renderWalletSelectionButton = () => { if (this.state.renderWalletSelectionButtonHidden) return; return ( - + {!this.state.isLoading && ( - this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.ONCHAIN }) + this.props.navigation.navigate("SelectWallet", { + onWalletSelect: this.onWalletSelect, + chainType: Chain.ONCHAIN + }) } > - {loc.wallets.select_wallet.toLowerCase()} - + + {loc.wallets.select_wallet.toLowerCase()} + + )} - + - this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelect, chainType: Chain.ONCHAIN }) + this.props.navigation.navigate("SelectWallet", { + onWalletSelect: this.onWalletSelect, + chainType: Chain.ONCHAIN + }) } > - {this.state.fromWallet.getLabel()} + + {this.state.fromWallet.getLabel()} + @@ -830,7 +1080,14 @@ export default class SendDetails extends Component { let rows = []; for (let [index, item] of this.state.addresses.entries()) { rows.push( - + this.setState({ isAmountToolbarVisibleForAndroid: true })} - onBlur={() => this.setState({ isAmountToolbarVisibleForAndroid: false })} + inputAccessoryViewID={ + this.state.fromWallet.allowSendMax() + ? BlueUseAllFundsButton.InputAccessoryViewID + : null + } + onFocus={() => + this.setState({ isAmountToolbarVisibleForAndroid: true }) + } + onBlur={() => + this.setState({ isAmountToolbarVisibleForAndroid: false }) + } /> { text = text.trim(); let transactions = this.state.addresses; try { - const { recipient, memo, fee, feeSliderValue } = await this.processBIP70Invoice(text); + const { + recipient, + memo, + fee, + feeSliderValue + } = await this.processBIP70Invoice(text); transactions[index].address = recipient.address; transactions[index].amount = recipient.amount; - this.setState({ addresses: transactions, memo: memo, fee, feeSliderValue, isLoading: false }); + this.setState({ + addresses: transactions, + memo: memo, + fee, + feeSliderValue, + isLoading: false + }); } catch (_e) { const { address, amount, memo } = this.decodeBitcoinUri(text); item.address = address || text; @@ -862,67 +1138,98 @@ export default class SendDetails extends Component { addresses: transactions, memo: memo || this.state.memo, isLoading: false, - bip70TransactionExpiration: null, + bip70TransactionExpiration: null }); } }} onBarScanned={this.processAddressData} address={item.address} isLoading={this.state.isLoading} - inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} + inputAccessoryViewID={ + BlueDismissKeyboardInputAccessory.InputAccessoryViewID + } /> {this.state.addresses.length > 1 && ( - + {index + 1} of {this.state.addresses.length} )} - , + ); } return rows; }; onUseAllPressed = () => { - ReactNativeHapticFeedback.trigger('notificationWarning'); + ReactNativeHapticFeedback.trigger("notificationWarning"); Alert.alert( - 'Use full balance', + "Use full balance", `Are you sure you want to use your wallet's full balance for this transaction? ${ - this.state.addresses.length > 1 ? 'Your other recipients will be removed from this transaction.' : '' + this.state.addresses.length > 1 + ? "Your other recipients will be removed from this transaction." + : "" }`, [ { text: loc._.ok, onPress: async () => { Keyboard.dismiss(); - const recipient = this.state.addresses[this.state.recipientsScrollIndex]; + const recipient = this.state.addresses[ + this.state.recipientsScrollIndex + ]; recipient.amount = BitcoinUnit.MAX; - this.setState({ addresses: [recipient], recipientsScrollIndex: 0, isAdvancedTransactionOptionsVisible: false }); + this.setState({ + addresses: [recipient], + recipientsScrollIndex: 0, + isAdvancedTransactionOptionsVisible: false + }); }, - style: 'default', + style: "default" }, - { text: loc.send.details.cancel, onPress: () => {}, style: 'cancel' }, + { text: loc.send.details.cancel, onPress: () => {}, style: "cancel" } ], - { cancelable: false }, + { cancelable: false } ); }; render() { - if (this.state.isLoading || typeof this.state.fromWallet === 'undefined') { + if (this.state.isLoading || typeof this.state.fromWallet === "undefined") { return ( - + ); } return ( - + (this.scrollView = ref)} onContentSizeChange={() => this.scrollView.scrollToEnd()} onLayout={() => this.scrollView.scrollToEnd()} @@ -935,52 +1242,91 @@ export default class SendDetails extends Component { this.setState({ memo: text })} - placeholder={loc.send.details.note_placeholder.slice(0,1).toUpperCase() + loc.send.details.note_placeholder.slice(1, loc.send.details.note_placeholder.length)} + placeholder={ + loc.send.details.note_placeholder + .slice(0, 1) + .toUpperCase() + + loc.send.details.note_placeholder.slice( + 1, + loc.send.details.note_placeholder.length + ) + } placeholderTextColor={BlueApp.settings.alternativeTextColor} value={this.state.memo} numberOfLines={1} - style={{ color: BlueApp.settings.foregroundColor, flex: 1, marginHorizontal: 8, minHeight: 33 }} + style={{ + color: BlueApp.settings.foregroundColor, + flex: 1, + marginHorizontal: 8, + minHeight: 33 + }} editable={!this.state.isLoading} onSubmitEditing={Keyboard.dismiss} - inputAccessoryViewID={BlueDismissKeyboardInputAccessory.InputAccessoryViewID} + inputAccessoryViewID={ + BlueDismissKeyboardInputAccessory.InputAccessoryViewID + } /> this.setState({ isFeeSelectionModalVisible: true })} + onPress={() => + this.setState({ isFeeSelectionModalVisible: true }) + } disabled={this.state.isLoading} - style={{ flexDirection: 'row', marginHorizontal: 20, justifyContent: 'space-between', alignItems: 'center' }} + style={{ + flexDirection: "row", + marginHorizontal: 20, + justifyContent: "space-between", + alignItems: "center" + }} > - Fee + Fee - {this.state.fee} - sat/b + + {this.state.fee} + + + sat/b + {this.renderCreateButton()} @@ -990,10 +1336,18 @@ export default class SendDetails extends Component { {Platform.select({ - ios: , + ios: ( + + ), android: this.state.isAmountToolbarVisibleForAndroid && ( - - ), + + ) })} {this.renderWalletSelectionButton()} @@ -1007,35 +1361,35 @@ const styles = StyleSheet.create({ modalContent: { backgroundColor: BlueApp.settings.brandingColor, padding: 22, - justifyContent: 'center', - alignItems: 'center', + justifyContent: "center", + alignItems: "center", borderTopLeftRadius: 16, borderTopRightRadius: 16, - borderColor: 'rgba(0, 0, 0, 0.1)', + borderColor: "rgba(0, 0, 0, 0.1)", minHeight: 200, - height: 200, + height: 200 }, advancedTransactionOptionsModalContent: { backgroundColor: BlueApp.settings.brandingColor, padding: 22, borderTopLeftRadius: 16, borderTopRightRadius: 16, - borderColor: 'rgba(0, 0, 0, 0.1)', - minHeight: 130, + borderColor: "rgba(0, 0, 0, 0.1)", + minHeight: 130 }, bottomModal: { - justifyContent: 'flex-end', - margin: 0, + justifyContent: "flex-end", + margin: 0 }, satoshisTextInput: { - backgroundColor: '#d2f8d6', + backgroundColor: "#d2f8d6", minWidth: 127, height: 60, borderRadius: 8, - flexDirection: 'row', - justifyContent: 'center', - paddingHorizontal: 8, - }, + flexDirection: "row", + justifyContent: "center", + paddingHorizontal: 8 + } }); SendDetails.propTypes = { @@ -1054,8 +1408,8 @@ SendDetails.propTypes = { fromSecret: PropTypes.fromSecret, fromWallet: PropTypes.fromWallet, memo: PropTypes.string, - uri: PropTypes.string, - }), - }), - }), + uri: PropTypes.string + }) + }) + }) }; diff --git a/screen/send/psbtWithHardwareWallet.js b/screen/send/psbtWithHardwareWallet.js index 0a097245e90..715a192eb97 100644 --- a/screen/send/psbtWithHardwareWallet.js +++ b/screen/send/psbtWithHardwareWallet.js @@ -1,8 +1,17 @@ /* global alert */ -import React, { Component } from 'react'; -import { ActivityIndicator, TouchableOpacity, View, Dimensions, Image, TextInput, Clipboard, Linking } from 'react-native'; -import QRCode from 'react-native-qrcode-svg'; -import { Icon, Text } from 'react-native-elements'; +import React, { Component } from "react"; +import { + ActivityIndicator, + TouchableOpacity, + View, + Dimensions, + Image, + TextInput, + Clipboard, + Linking +} from "react-native"; +import QRCode from "react-native-qrcode-svg"; +import { Icon, Text } from "react-native-elements"; import { BlueButton, BlueText, @@ -10,33 +19,41 @@ import { BlueCard, BlueNavigationStyle, BlueSpacing20, - BlueCopyToClipboardButton, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import { RNCamera } from 'react-native-camera'; -let loc = require('../../loc'); -let EV = require('../../events'); -let BlueElectrum = require('../../BlueElectrum'); + BlueCopyToClipboardButton +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import { RNCamera } from "react-native-camera"; + +const loc = require("../../loc"); +const EV = require("../../events"); +const BlueElectrum = require("../../BlueElectrum"); /** @type {AppStorage} */ -const BlueApp = require('../../BlueApp'); -const bitcoin = require('bitcoinjs-lib'); -const { height, width } = Dimensions.get('window'); +const BlueApp = require("../../BlueApp"); +const bitcoin = require("bitcoinjs-lib"); + +const { height, width } = Dimensions.get("window"); export default class PsbtWithHardwareWallet extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(null, false), - title: loc.send.header, + title: loc.send.header }); cameraRef = null; onBarCodeRead = ret => { - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.pausePreview(); + if ( + RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.pausePreview(); this.setState({ renderScanner: false }, () => { console.log(ret.data); try { - let Tx = this.state.fromWallet.combinePsbt(this.state.psbt.toBase64(), ret.data); + const Tx = this.state.fromWallet.combinePsbt( + this.state.psbt.toBase64(), + ret.data + ); this.setState({ txhex: Tx.toHex() }); } catch (Err) { alert(Err); @@ -51,14 +68,14 @@ export default class PsbtWithHardwareWallet extends Component { isLoading: false, renderScanner: false, qrCodeHeight: height > width ? width - 40 : width / 2, - memo: props.navigation.getParam('memo'), - psbt: props.navigation.getParam('psbt'), - fromWallet: props.navigation.getParam('fromWallet'), + memo: props.navigation.getParam("memo"), + psbt: props.navigation.getParam("psbt"), + fromWallet: props.navigation.getParam("fromWallet") }; } async componentDidMount() { - console.log('send/psbtWithHardwareWallet - componentDidMount'); + console.log("send/psbtWithHardwareWallet - componentDidMount"); } broadcast = () => { @@ -66,23 +83,29 @@ export default class PsbtWithHardwareWallet extends Component { try { await BlueElectrum.ping(); await BlueElectrum.waitTillConnected(); - let result = await this.state.fromWallet.broadcastTx(this.state.txhex); + const result = await this.state.fromWallet.broadcastTx( + this.state.txhex + ); if (result) { - console.log('broadcast result = ', result); + console.log("broadcast result = ", result); EV(EV.enum.REMOTE_TRANSACTIONS_COUNT_CHANGED); // someone should fetch txs this.setState({ success: true, isLoading: false }); if (this.state.memo) { - let txDecoded = bitcoin.Transaction.fromHex(this.state.txhex); + const txDecoded = bitcoin.Transaction.fromHex(this.state.txhex); const txid = txDecoded.getId(); BlueApp.tx_metadata[txid] = { memo: this.state.memo }; } } else { - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); this.setState({ isLoading: false }); - alert('Broadcast failed'); + alert("Broadcast failed"); } } catch (error) { - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); this.setState({ isLoading: false }); alert(error.message); } @@ -95,13 +118,13 @@ export default class PsbtWithHardwareWallet extends Component { (this.cameraRef = ref)} - style={{ flex: 1, justifyContent: 'space-between' }} + style={{ flex: 1, justifyContent: "space-between" }} onBarCodeRead={this.onBarCodeRead} barCodeTypes={[RNCamera.Constants.BarCodeType.qr]} /> @@ -109,16 +132,19 @@ export default class PsbtWithHardwareWallet extends Component { style={{ width: 40, height: 40, - backgroundColor: 'rgba(0,0,0,0.4)', - justifyContent: 'center', + backgroundColor: "rgba(0,0,0,0.4)", + justifyContent: "center", borderRadius: 20, - position: 'absolute', + position: "absolute", right: 16, - top: 64, + top: 64 }} onPress={() => this.setState({ renderScanner: false })} > - + ); @@ -133,16 +159,19 @@ export default class PsbtWithHardwareWallet extends Component { width: 120, height: 120, borderRadius: 60, - alignSelf: 'center', - justifyContent: 'center', + alignSelf: "center", + justifyContent: "center", marginTop: 143, - marginBottom: 53, + marginBottom: 53 }} > - + ); @@ -151,20 +180,22 @@ export default class PsbtWithHardwareWallet extends Component { _renderBroadcastHex() { return ( - - {loc.send.create.this_is_hex} + + + {loc.send.create.this_is_hex} + - Clipboard.setString(this.state.txhex)}> - Copy and broadcast later + Clipboard.setString(this.state.txhex)} + > + + Copy and broadcast later + - Linking.openURL('https://coinb.in/?verify=' + this.state.txhex)}> - Verify on coinb.in + + Linking.openURL("https://coinb.in/?verify=" + this.state.txhex) + } + > + + Verify on coinb.in + - + ); @@ -200,23 +260,39 @@ export default class PsbtWithHardwareWallet extends Component { return ( - - + + - This is partially signed bitcoin transaction (PSBT). Please finish signing it with your hardware wallet. + + This is partially signed bitcoin transaction (PSBT). Please + finish signing it with your hardware wallet. + - this.setState({ renderScanner: true })} title={'Scan signed transaction'} /> + this.setState({ renderScanner: true })} + title={"Scan signed transaction"} + /> - - + + @@ -237,9 +313,9 @@ PsbtWithHardwareWallet.propTypes = { memo: PropTypes.string, fromWallet: PropTypes.shape({ fromAddress: PropTypes.string, - fromSecret: PropTypes.string, - }), - }), - }), - }), + fromSecret: PropTypes.string + }) + }) + }) + }) }; diff --git a/screen/send/scanQrAddress.js b/screen/send/scanQrAddress.js index 2fe7fa36239..01142fe9ca8 100644 --- a/screen/send/scanQrAddress.js +++ b/screen/send/scanQrAddress.js @@ -1,23 +1,27 @@ /* global alert */ -import React from 'react'; -import { Image, TouchableOpacity, Platform } from 'react-native'; -import PropTypes from 'prop-types'; -import { RNCamera } from 'react-native-camera'; -import { SafeBlueArea } from '../../BlueComponents'; -import { Icon } from 'react-native-elements'; -import ImagePicker from 'react-native-image-picker'; -const LocalQRCode = require('@remobile/react-native-qrcode-local-image'); +import React from "react"; +import { Image, TouchableOpacity, Platform } from "react-native"; +import PropTypes from "prop-types"; +import { RNCamera } from "react-native-camera"; +import { SafeBlueArea } from "../../BlueComponents"; +import { Icon } from "react-native-elements"; +import ImagePicker from "react-native-image-picker"; + +const LocalQRCode = require("@remobile/react-native-qrcode-local-image"); export default class ScanQRCode extends React.Component { static navigationOptions = { - header: null, + header: null }; cameraRef = null; onBarCodeRead = ret => { - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.pausePreview(); - const onBarScannedProp = this.props.navigation.getParam('onBarScanned'); + if ( + RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.pausePreview(); + const onBarScannedProp = this.props.navigation.getParam("onBarScanned"); this.props.navigation.goBack(); onBarScannedProp(ret.data); }; // end @@ -28,13 +32,13 @@ export default class ScanQRCode extends React.Component { (this.cameraRef = ref)} - style={{ flex: 1, justifyContent: 'space-between' }} + style={{ flex: 1, justifyContent: "space-between" }} onBarCodeRead={this.onBarCodeRead} barCodeTypes={[RNCamera.Constants.BarCodeType.qr]} /> @@ -42,51 +46,69 @@ export default class ScanQRCode extends React.Component { style={{ width: 40, height: 40, - backgroundColor: 'rgba(0,0,0,0.4)', - justifyContent: 'center', + backgroundColor: "rgba(0,0,0,0.4)", + justifyContent: "center", borderRadius: 20, - position: 'absolute', + position: "absolute", right: 16, - top: 64, + top: 64 }} onPress={() => this.props.navigation.goBack(null)} > - + { - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.pausePreview(); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.pausePreview(); ImagePicker.launchImageLibrary( { title: null, - mediaType: 'photo', - takePhotoButtonTitle: null, + mediaType: "photo", + takePhotoButtonTitle: null }, response => { if (response.uri) { - const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.path.toString(); + const uri = + Platform.OS === "ios" + ? response.uri.toString().replace("file://", "") + : response.path.toString(); LocalQRCode.decode(uri, (error, result) => { if (!error) { this.onBarCodeRead({ data: result }); } else { - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.resumePreview(); - alert('The selected image does not contain a QR Code.'); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.resumePreview(); + alert("The selected image does not contain a QR Code."); } }); } else { - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.resumePreview(); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.resumePreview(); } - }, + } ); }} > @@ -101,6 +123,6 @@ ScanQRCode.propTypes = { navigation: PropTypes.shape({ goBack: PropTypes.func, dismiss: PropTypes.func, - getParam: PropTypes.func, - }), + getParam: PropTypes.func + }) }; diff --git a/screen/send/success.js b/screen/send/success.js index 59a71d26934..83ea64c96ba 100644 --- a/screen/send/success.js +++ b/screen/send/success.js @@ -1,46 +1,56 @@ -import React, { Component } from 'react'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import { View } from 'react-native'; -import { Text, Icon } from 'react-native-elements'; -import { BlueButton, SafeBlueArea, BlueCard } from '../../BlueComponents'; -import { BitcoinUnit } from '../../models/bitcoinUnits'; -import PropTypes from 'prop-types'; -let loc = require('../../loc'); -let BlueApp = require('../../BlueApp'); +import React, { Component } from "react"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import { View } from "react-native"; +import { Text, Icon } from "react-native-elements"; +import { BlueButton, SafeBlueArea, BlueCard } from "../../BlueComponents"; +import { BitcoinUnit } from "../../models/bitcoinUnits"; +import PropTypes from "prop-types"; + +const loc = require("../../loc"); +const BlueApp = require("../../BlueApp"); export default class Success extends Component { static navigationOptions = { header: null, - gesturesEnabled: false, + gesturesEnabled: false }; constructor(props) { super(props); - console.log('send/success constructor'); + console.log("send/success constructor"); this.state = { - amount: props.navigation.getParam('amount'), - fee: props.navigation.getParam('fee') || 0, - amountUnit: props.navigation.getParam('amountUnit') || BitcoinUnit.BTC, - invoiceDescription: props.navigation.getParam('invoiceDescription') || '', + amount: props.navigation.getParam("amount"), + fee: props.navigation.getParam("fee") || 0, + amountUnit: props.navigation.getParam("amountUnit") || BitcoinUnit.BTC, + invoiceDescription: props.navigation.getParam("invoiceDescription") || "" }; } async componentDidMount() { - console.log('send/success - componentDidMount'); - ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false }); + console.log("send/success - componentDidMount"); + ReactNativeHapticFeedback.trigger("notificationSuccess", { + ignoreAndroidSystemSettings: false + }); } render() { return ( - - + + {this.state.amount} @@ -51,22 +61,22 @@ export default class Success extends Component { fontSize: 16, marginHorizontal: 4, paddingBottom: 6, - fontWeight: '600', - alignSelf: 'flex-end', + fontWeight: "600", + alignSelf: "flex-end" }} > - {' ' + this.state.amountUnit} + {" " + this.state.amountUnit} {this.state.fee > 0 && ( {loc.send.create.fee}: {this.state.fee} {BitcoinUnit.BTC} @@ -76,12 +86,12 @@ export default class Success extends Component { {this.state.invoiceDescription} @@ -94,10 +104,10 @@ export default class Success extends Component { width: 120, height: 120, borderRadius: 60, - alignSelf: 'center', - justifyContent: 'center', + alignSelf: "center", + justifyContent: "center", marginTop: 43, - marginBottom: 53, + marginBottom: 53 }} > @@ -124,8 +134,8 @@ Success.propTypes = { state: PropTypes.shape({ params: PropTypes.shape({ amount: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - fee: PropTypes.number, - }), - }), - }), + fee: PropTypes.number + }) + }) + }) }; diff --git a/screen/settings/about.js b/screen/settings/about.js index d8fbabfa4e1..a349bce068d 100644 --- a/screen/settings/about.js +++ b/screen/settings/about.js @@ -1,5 +1,5 @@ -import React, { Component } from 'react'; -import { ScrollView, Linking, Dimensions } from 'react-native'; +import React, { Component } from "react"; +import { ScrollView, Linking, Dimensions } from "react-native"; import { BlueTextCentered, BlueLoading, @@ -9,32 +9,38 @@ import { SafeBlueArea, BlueCard, BlueText, - BlueNavigationStyle, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { getApplicationName, getVersion, getBundleId, getBuildNumber } from 'react-native-device-info'; -import Rate, { AndroidMarket } from 'react-native-rate'; + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { + getApplicationName, + getVersion, + getBundleId, + getBuildNumber +} from "react-native-device-info"; +import Rate, { AndroidMarket } from "react-native-rate"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -const { width, height } = Dimensions.get('window'); -const loc = require('../../loc/'); +const BlueApp = require("../../BlueApp"); + +const { width, height } = Dimensions.get("window"); +const loc = require("../../loc/"); export default class About extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(), - title: loc.settings.about, + title: loc.settings.about }); constructor(props) { super(props); this.state = { - isLoading: true, + isLoading: true }; } async componentDidMount() { this.setState({ - isLoading: false, + isLoading: false }); } @@ -44,10 +50,12 @@ export default class About extends Component { } return ( - + - Veles Wallet is a free and open source wallet. Licensed MIT. + + Veles Wallet is a free and open source wallet. Licensed MIT. + Always backup your keys ! @@ -55,12 +63,14 @@ export default class About extends Component { { - Linking.openURL('https://github.com/velescore/veles-mobile-wallet'); + Linking.openURL( + "https://github.com/velescore/veles-mobile-wallet" + ); }} title="github.com/velescore/veles-mobile-wallet" /> @@ -68,22 +78,22 @@ export default class About extends Component { { - let options = { - AppleAppID: '1376878040', - GooglePackageName: 'io.veles.wallet', + const options = { + AppleAppID: "1376878040", + GooglePackageName: "io.veles.wallet", preferredAndroidMarket: AndroidMarket.Google, preferInApp: true, openAppStoreIfInAppFails: true, - fallbackPlatformURL: 'https://veles.network', + fallbackPlatformURL: "https://veles.network" }; Rate.rate(options, success => { if (success) { - console.log('User Rated.'); + console.log("User Rated."); } }); }} @@ -106,7 +116,7 @@ export default class About extends Component { { - this.props.navigation.navigate('ReleaseNotes'); + this.props.navigation.navigate("ReleaseNotes"); }} title="Release notes" /> @@ -114,9 +124,12 @@ export default class About extends Component { - {getApplicationName()} ver {getVersion()} (build {getBuildNumber()}) + {getApplicationName()} ver {getVersion()} (build{" "} + {getBuildNumber()}) + + + {new Date(getBuildNumber() * 1000).toGMTString()} - {new Date(getBuildNumber() * 1000).toGMTString()} {getBundleId()} w, h = {width}, {height} @@ -131,6 +144,6 @@ export default class About extends Component { About.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/settings/currency.js b/screen/settings/currency.js index c511b196c04..c1c63224b32 100644 --- a/screen/settings/currency.js +++ b/screen/settings/currency.js @@ -1,21 +1,36 @@ -import React, { Component } from 'react'; -import { FlatList, TouchableOpacity, ActivityIndicator, View } from 'react-native'; -import { SafeBlueArea, BlueNavigationStyle, BlueListItem, BlueText, BlueCard } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { Icon } from 'react-native-elements'; -import { FiatUnit } from '../../models/fiatUnit'; -let loc = require('../../loc'); -let currency = require('../../currency'); +import React, { Component } from "react"; +import { + FlatList, + TouchableOpacity, + ActivityIndicator, + View +} from "react-native"; +import { + SafeBlueArea, + BlueNavigationStyle, + BlueListItem, + BlueText, + BlueCard +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { Icon } from "react-native-elements"; +import { FiatUnit } from "../../models/fiatUnit"; + +const loc = require("../../loc"); +const currency = require("../../currency"); export default class Currency extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(), - title: loc.settings.currency, + title: loc.settings.currency }); constructor(props) { super(props); - this.state = { data: Object.values(FiatUnit), isSavingNewPreferredCurrency: false }; + this.state = { + data: Object.values(FiatUnit), + isSavingNewPreferredCurrency: false + }; } async componentDidMount() { @@ -34,22 +49,25 @@ export default class Currency extends Component { return ( { - this.setState({ isSavingNewPreferredCurrency: true, selectedCurrency: item }, async () => { - await currency.setPrefferedCurrency(item); - await currency.startUpdater(); - this.setState({ isSavingNewPreferredCurrency: false }); - }); + this.setState( + { isSavingNewPreferredCurrency: true, selectedCurrency: item }, + async () => { + await currency.setPrefferedCurrency(item); + await currency.startUpdater(); + this.setState({ isSavingNewPreferredCurrency: false }); + } + ); }} > ) : ( - ), + ) } : { hideChevron: true })} /> @@ -58,9 +76,12 @@ export default class Currency extends Component { }; render() { - if (this.state.selectedCurrency !== null && this.state.selectedCurrency !== undefined) { + if ( + this.state.selectedCurrency !== null && + this.state.selectedCurrency !== undefined + ) { return ( - + `${index}`} @@ -75,7 +96,7 @@ export default class Currency extends Component { ); } return ( - + ); @@ -85,6 +106,6 @@ export default class Currency extends Component { Currency.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/settings/defaultView.js b/screen/settings/defaultView.js index fa944e747c8..b4a843f2055 100644 --- a/screen/settings/defaultView.js +++ b/screen/settings/defaultView.js @@ -1,24 +1,29 @@ -import React, { Component } from 'react'; -import { TouchableOpacity, View } from 'react-native'; -import { SafeBlueArea, BlueNavigationStyle, BlueListItem } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import OnAppLaunch from '../../class/onAppLaunch'; -const BlueApp = require('../../BlueApp'); +import React, { Component } from "react"; +import { TouchableOpacity, View } from "react-native"; +import { + SafeBlueArea, + BlueNavigationStyle, + BlueListItem +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import OnAppLaunch from "../../class/onAppLaunch"; + +const BlueApp = require("../../BlueApp"); export default class DefaultView extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(), - title: 'On Launch', + title: "On Launch" }); constructor(props) { super(props); - this.state = { defaultWalletLabel: '', viewAllWalletsEnabled: true }; + this.state = { defaultWalletLabel: "", viewAllWalletsEnabled: true }; } async componentDidMount() { const viewAllWalletsEnabled = await OnAppLaunch.isViewAllWalletsEnabled(); - let defaultWalletLabel = ''; + let defaultWalletLabel = ""; const wallet = await OnAppLaunch.getSelectedDefaultWallet(); if (wallet) { defaultWalletLabel = wallet.getLabel(); @@ -27,28 +32,39 @@ export default class DefaultView extends Component { } selectWallet = () => { - this.props.navigation.navigate('SelectWallet', { onWalletSelect: this.onWalletSelectValueChanged }); + this.props.navigation.navigate("SelectWallet", { + onWalletSelect: this.onWalletSelectValueChanged + }); }; onViewAllWalletsSwitchValueChanged = async value => { await OnAppLaunch.setViewAllWalletsEnabled(value); if (value) { - return this.setState({ viewAllWalletsEnabled: true, defaultWalletLabel: '' }); + return this.setState({ + viewAllWalletsEnabled: true, + defaultWalletLabel: "" + }); } else { const selectedWallet = await OnAppLaunch.getSelectedDefaultWallet(); - return this.setState({ viewAllWalletsEnabled: false, defaultWalletLabel: selectedWallet.getLabel() }); + return this.setState({ + viewAllWalletsEnabled: false, + defaultWalletLabel: selectedWallet.getLabel() + }); } }; onWalletSelectValueChanged = async wallet => { await OnAppLaunch.setViewAllWalletsEnabled(false); await OnAppLaunch.setSelectedDefaultWallet(wallet.getID()); - this.setState({ defaultWalletLabel: wallet.getLabel(), viewAllWalletsEnabled: false }, () => this.props.navigation.pop()); + this.setState( + { defaultWalletLabel: wallet.getLabel(), viewAllWalletsEnabled: false }, + () => this.props.navigation.pop() + ); }; render() { return ( - + ({ ...BlueNavigationStyle(), - title: loc.settings.electrum_settings, + title: loc.settings.electrum_settings }); constructor(props) { super(props); this.state = { isLoading: true, - config: {}, + config: {} }; } async componentDidMount() { - let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST); - let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT); + const host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST); + const port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT); this.setState({ isLoading: false, host, - port, + port }); await this.setState({ - config: await BlueElectrum.getConfig(), + config: await BlueElectrum.getConfig() }); } save = () => { this.setState({ isLoading: true }, async () => { - this.state.host = this.state.host ? this.state.host : ''; - this.state.port = this.state.port ? this.state.port : ''; + this.state.host = this.state.host ? this.state.host : ""; + this.state.port = this.state.port ? this.state.port : ""; try { if (!this.state.host && !this.state.port) { - await AsyncStorage.setItem(AppStorage.ELECTRUM_HOST, ''); - await AsyncStorage.setItem(AppStorage.ELECTRUM_TCP_PORT, ''); - alert('Your changes have been saved successfully. Restart may be required for changes to take effect.'); - } else if (!(await BlueElectrum.testConnection(this.state.host, this.state.port))) { + await AsyncStorage.setItem(AppStorage.ELECTRUM_HOST, ""); + await AsyncStorage.setItem(AppStorage.ELECTRUM_TCP_PORT, ""); + alert( + "Your changes have been saved successfully. Restart may be required for changes to take effect." + ); + } else if ( + !(await BlueElectrum.testConnection(this.state.host, this.state.port)) + ) { alert("Can't connect to provided Electrum server"); } else { await AsyncStorage.setItem(AppStorage.ELECTRUM_HOST, this.state.host); - await AsyncStorage.setItem(AppStorage.ELECTRUM_TCP_PORT, this.state.port); - alert('Your changes have been saved successfully. Restart may be required for changes to take effect.'); + await AsyncStorage.setItem( + AppStorage.ELECTRUM_TCP_PORT, + this.state.port + ); + alert( + "Your changes have been saved successfully. Restart may be required for changes to take effect." + ); } } catch (_) {} this.setState({ isLoading: false }); @@ -61,31 +79,37 @@ export default class ElectrumSettings extends Component { render() { return ( - + {loc.settings.electrum_settings_explain} this.setState({ host: text })} numberOfLines={1} - style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36, color: BlueApp.settings.foregroundColor }} + style={{ + flex: 1, + marginHorizontal: 8, + minHeight: 36, + height: 36, + color: BlueApp.settings.foregroundColor + }} editable={!this.state.isLoading} underlineColorAndroid="transparent" /> @@ -93,31 +117,41 @@ export default class ElectrumSettings extends Component { this.setState({ port: text })} numberOfLines={1} - style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36, color: BlueApp.settings.foregroundColor }} + style={{ + flex: 1, + marginHorizontal: 8, + minHeight: 36, + height: 36, + color: BlueApp.settings.foregroundColor + }} editable={!this.state.isLoading} underlineColorAndroid="transparent" /> - {this.state.isLoading ? : } + {this.state.isLoading ? ( + + ) : ( + + )} @@ -125,7 +159,9 @@ export default class ElectrumSettings extends Component { Currently using: Host: {this.state.config.host} Port: {this.state.config.port} - Connected: {(this.state.config.status === 1 && 'Yes') || 'No'} + + Connected: {(this.state.config.status === 1 && "Yes") || "No"} + ); @@ -135,6 +171,6 @@ export default class ElectrumSettings extends Component { ElectrumSettings.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/settings/encryptStorage.js b/screen/settings/encryptStorage.js index 1b77812329b..2152c23ea29 100644 --- a/screen/settings/encryptStorage.js +++ b/screen/settings/encryptStorage.js @@ -1,32 +1,40 @@ /* global alert */ -import React, { Component } from 'react'; -import { View } from 'react-native'; -import { FormValidationMessage } from 'react-native-elements'; -import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents'; -import PropTypes from 'prop-types'; +import React, { Component } from "react"; +import { View } from "react-native"; +import { FormValidationMessage } from "react-native-elements"; +import { + BlueLoading, + BlueSpacing20, + BlueButton, + SafeBlueArea, + BlueCard, + BlueText, + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let prompt = require('../../prompt'); -let loc = require('../../loc'); +const BlueApp = require("../../BlueApp"); +const prompt = require("../../prompt"); +const loc = require("../../loc"); export default class EncryptStorage extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(), - title: loc.settings.encrypt_storage, + title: loc.settings.encrypt_storage }); constructor(props) { super(props); this.state = { isLoading: true, - language: loc.getLanguage(), + language: loc.getLanguage() }; } async componentDidMount() { this.setState({ isLoading: false, - storageIsEncrypted: await BlueApp.storageIsEncrypted(), + storageIsEncrypted: await BlueApp.storageIsEncrypted() }); } @@ -36,7 +44,7 @@ export default class EncryptStorage extends Component { } return ( - + {(() => { if (this.state.storageIsEncrypted) { @@ -45,7 +53,9 @@ export default class EncryptStorage extends Component { {loc.settings.storage_encrypted} this.props.navigation.navigate('PlausibleDeniability')} + onPress={() => + this.props.navigation.navigate("PlausibleDeniability") + } title={loc.settings.plausible_deniability} /> @@ -53,17 +63,22 @@ export default class EncryptStorage extends Component { } else { return ( - {loc.settings.storage_not_encrypted} + + {loc.settings.storage_not_encrypted} + { this.setState({ isLoading: true }); - let p1 = await prompt(loc.settings.password, loc.settings.password_explain).catch(() => { + let p1 = await prompt( + loc.settings.password, + loc.settings.password_explain + ).catch(() => { this.setState({ isLoading: false }); p1 = undefined; }); @@ -71,14 +86,17 @@ export default class EncryptStorage extends Component { this.setState({ isLoading: false }); return; } - let p2 = await prompt(loc.settings.password, loc.settings.retype_password).catch(() => { + const p2 = await prompt( + loc.settings.password, + loc.settings.retype_password + ).catch(() => { this.setState({ isLoading: false }); }); if (p1 === p2) { await BlueApp.encryptStorage(p1); this.setState({ isLoading: false, - storageIsEncrypted: await BlueApp.storageIsEncrypted(), + storageIsEncrypted: await BlueApp.storageIsEncrypted() }); } else { this.setState({ isLoading: false }); @@ -100,6 +118,6 @@ export default class EncryptStorage extends Component { EncryptStorage.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/settings/language.js b/screen/settings/language.js index 539aebfe821..5eaa6723889 100644 --- a/screen/settings/language.js +++ b/screen/settings/language.js @@ -1,14 +1,22 @@ -import React, { Component } from 'react'; -import { FlatList, TouchableOpacity } from 'react-native'; -import { BlueLoading, BlueText, SafeBlueArea, BlueListItem, BlueCard, BlueNavigationStyle } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { Icon } from 'react-native-elements'; -let loc = require('../../loc'); +import React, { Component } from "react"; +import { FlatList, TouchableOpacity } from "react-native"; +import { + BlueLoading, + BlueText, + SafeBlueArea, + BlueListItem, + BlueCard, + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { Icon } from "react-native-elements"; + +const loc = require("../../loc"); export default class Language extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(), - title: loc.settings.language, + title: loc.settings.language }); constructor(props) { @@ -17,41 +25,41 @@ export default class Language extends Component { isLoading: true, language: loc.getLanguage(), availableLanguages: [ - { label: 'English', value: 'en' }, - { label: 'Afrikaans (AFR)', value: 'zar_afr' }, - { label: 'Chinese (ZH)', value: 'zh_cn' }, - { label: 'Chinese (TW)', value: 'zh_tw' }, - { label: 'Croatian (HR)', value: 'hr_hr' }, - { label: 'Česky (CZ)', value: 'cs_cz' }, - { label: 'Danish (DK)', value: 'da_dk' }, - { label: 'Deutsch (DE)', value: 'de_de' }, - { label: 'Español (ES)', value: 'es' }, - { label: 'Ελληνικά (EL)', value: 'el' }, - { label: 'Italiano (IT)', value: 'it' }, - { label: 'Suomi (FI)', value: 'fi_fi' }, - { label: 'Français (FR)', value: 'fr_fr' }, - { label: 'Indonesia (ID)', value: 'id_id' }, - { label: '日本語 (JP)', value: 'jp_jp' }, - { label: '한국어 (KO)', value: 'ko_kr' }, - { label: 'Magyar (HU)', value: 'hu_hu' }, - { label: 'Nederlands (NL)', value: 'nl_nl' }, - { label: 'Norsk (NB)', value: 'nb_no' }, - { label: 'Português (BR)', value: 'pt_br' }, - { label: 'Português (PT)', value: 'pt_pt' }, - { label: 'Русский', value: 'ru' }, - { label: 'Svenska (SE)', value: 'sv_se' }, - { label: 'Thai (TH)', value: 'th_th' }, - { label: 'Vietnamese (VN)', value: 'vi_vn' }, - { label: 'Українська', value: 'ua' }, - { label: 'Türkçe (TR)', value: 'tr_tr' }, - { label: 'Xhosa (XHO)', value: 'zar_xho' }, - ], + { label: "English", value: "en" }, + { label: "Afrikaans (AFR)", value: "zar_afr" }, + { label: "Chinese (ZH)", value: "zh_cn" }, + { label: "Chinese (TW)", value: "zh_tw" }, + { label: "Croatian (HR)", value: "hr_hr" }, + { label: "Česky (CZ)", value: "cs_cz" }, + { label: "Danish (DK)", value: "da_dk" }, + { label: "Deutsch (DE)", value: "de_de" }, + { label: "Español (ES)", value: "es" }, + { label: "Ελληνικά (EL)", value: "el" }, + { label: "Italiano (IT)", value: "it" }, + { label: "Suomi (FI)", value: "fi_fi" }, + { label: "Français (FR)", value: "fr_fr" }, + { label: "Indonesia (ID)", value: "id_id" }, + { label: "日本語 (JP)", value: "jp_jp" }, + { label: "한국어 (KO)", value: "ko_kr" }, + { label: "Magyar (HU)", value: "hu_hu" }, + { label: "Nederlands (NL)", value: "nl_nl" }, + { label: "Norsk (NB)", value: "nb_no" }, + { label: "Português (BR)", value: "pt_br" }, + { label: "Português (PT)", value: "pt_pt" }, + { label: "Русский", value: "ru" }, + { label: "Svenska (SE)", value: "sv_se" }, + { label: "Thai (TH)", value: "th_th" }, + { label: "Vietnamese (VN)", value: "vi_vn" }, + { label: "Українська", value: "ua" }, + { label: "Türkçe (TR)", value: "tr_tr" }, + { label: "Xhosa (XHO)", value: "zar_xho" } + ] }; } async componentDidMount() { this.setState({ - isLoading: false, + isLoading: false }); } @@ -59,7 +67,7 @@ export default class Language extends Component { return ( { - console.warn('setLanguage', item.value); + console.warn("setLanguage", item.value); loc.saveLanguage(item.value); return this.setState({ language: item.value }); }} @@ -68,7 +76,9 @@ export default class Language extends Component { title={item.label} {...(this.state.language === item.value ? { - rightIcon: , + rightIcon: ( + + ) } : { hideChevron: true })} /> @@ -82,7 +92,7 @@ export default class Language extends Component { } return ( - + `${index}`} @@ -91,7 +101,10 @@ export default class Language extends Component { renderItem={this.renderItem} /> - When selecting a new language, restarting Veles Wallet may be required for the change to take effect. + + When selecting a new language, restarting Veles Wallet may be + required for the change to take effect. + ); @@ -101,6 +114,6 @@ export default class Language extends Component { Language.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/settings/releasenotes.js b/screen/settings/releasenotes.js index 328bda9ea7b..73211fc1857 100644 --- a/screen/settings/releasenotes.js +++ b/screen/settings/releasenotes.js @@ -1,20 +1,26 @@ -import React, { Component } from 'react'; -import { ScrollView } from 'react-native'; -import { BlueLoading, SafeBlueArea, BlueCard, BlueText, BlueNavigationStyle } from '../../BlueComponents'; -import PropTypes from 'prop-types'; +import React, { Component } from "react"; +import { ScrollView } from "react-native"; +import { + BlueLoading, + SafeBlueArea, + BlueCard, + BlueText, + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; /** @type {AppStorage} */ -const notes = require('../../release-notes'); +const notes = require("../../release-notes"); export default class ReleaseNotes extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(), - title: 'Release notes', + title: "Release notes" }); constructor(props) { super(props); this.state = { - isLoading: true, + isLoading: true }; } @@ -22,7 +28,7 @@ export default class ReleaseNotes extends Component { console.log(notes); this.setState({ isLoading: false, - notes: notes, + notes: notes }); } @@ -32,7 +38,7 @@ export default class ReleaseNotes extends Component { } return ( - + {this.state.notes} @@ -46,6 +52,6 @@ export default class ReleaseNotes extends Component { ReleaseNotes.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/settings/settings.js b/screen/settings/settings.js index a58e84601bd..2504956bb36 100644 --- a/screen/settings/settings.js +++ b/screen/settings/settings.js @@ -1,5 +1,5 @@ -import React, { Component, useEffect, useState } from 'react'; -import { ScrollView, View, Switch, TouchableOpacity } from 'react-native'; +import React, { Component, useEffect, useState } from "react"; +import { ScrollView, View, Switch, TouchableOpacity } from "react-native"; import { BlueText, BlueCard, @@ -7,36 +7,47 @@ import { SafeBlueArea, BlueNavigationStyle, BlueHeaderDefaultSub, - BlueListItem, -} from '../../BlueComponents'; -import AsyncStorage from '@react-native-community/async-storage'; -import { AppStorage } from '../../class'; -import Biometric from '../../class/biometrics'; -import { useNavigation } from 'react-navigation-hooks'; -const BlueApp = require('../../BlueApp'); -const loc = require('../../loc'); + BlueListItem +} from "../../BlueComponents"; +import AsyncStorage from "@react-native-community/async-storage"; +import { AppStorage } from "../../class"; +import Biometric from "../../class/biometrics"; +import { useNavigation } from "react-navigation-hooks"; + +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); export const Settings = () => { const [isLoading, setIsLoading] = useState(true); const [showAdvancedOptions, setShowAdvancedOptions] = useState(false); const [advancedModeEnabled, setAdvancedModeEnabled] = useState(false); - const [biometrics, setBiometrics] = useState({ isDeviceBiometricCapable: false, isBiometricsEnabled: false, biometricsType: '' }); + const [biometrics, setBiometrics] = useState({ + isDeviceBiometricCapable: false, + isBiometricsEnabled: false, + biometricsType: "" + }); const { navigate } = useNavigation(); useEffect(() => { (async () => { - setAdvancedModeEnabled(!!(await AsyncStorage.getItem(AppStorage.ADVANCED_MODE_ENABLED))); + setAdvancedModeEnabled( + !!(await AsyncStorage.getItem(AppStorage.ADVANCED_MODE_ENABLED)) + ); const isBiometricsEnabled = await Biometric.isBiometricUseEnabled(); const isDeviceBiometricCapable = await Biometric.isDeviceBiometricCapable(); - const biometricsType = (await Biometric.biometricType()) || 'biometrics'; - setBiometrics({ isBiometricsEnabled, isDeviceBiometricCapable, biometricsType }); + const biometricsType = (await Biometric.biometricType()) || "biometrics"; + setBiometrics({ + isBiometricsEnabled, + isDeviceBiometricCapable, + biometricsType + }); setIsLoading(false); })(); }); const onAdvancedModeSwitch = async value => { if (value) { - await AsyncStorage.setItem(AppStorage.ADVANCED_MODE_ENABLED, '1'); + await AsyncStorage.setItem(AppStorage.ADVANCED_MODE_ENABLED, "1"); } else { await AsyncStorage.removeItem(AppStorage.ADVANCED_MODE_ENABLED); } @@ -44,7 +55,7 @@ export const Settings = () => { }; const onUseBiometricSwitch = async value => { - let isBiometricsEnabled = biometrics; + const isBiometricsEnabled = biometrics; if (await Biometric.unlockWithBiometrics()) { isBiometricsEnabled.isBiometricsEnabled = value; await Biometric.setBiometricUseEnabled(value); @@ -59,12 +70,20 @@ export const Settings = () => { return isLoading ? ( ) : ( - + {BlueApp.getWallets().length > 1 && ( - navigate('DefaultView')} title="On Launch" /> + navigate("DefaultView")} + title="On Launch" + /> )} - navigate('EncryptStorage')} component={TouchableOpacity} /> + navigate("EncryptStorage")} + component={TouchableOpacity} + /> {biometrics.isDeviceBiometricCapable && ( { switched={biometrics.isBiometricsEnabled} /> )} - navigate('Language')} /> - navigate('ElectrumSettings')} /> - + navigate("Language")} + /> + navigate("ElectrumSettings")} + /> + {showAdvancedOptions && ( - + {loc.settings.enable_advanced_mode} - + )} - navigate('About')} /> + navigate("About")} + /> ); @@ -95,10 +139,12 @@ export const Settings = () => { export default class SettingsContainer extends Component { static navigationOptions = { ...BlueNavigationStyle, - title: loc.settings.header.slice(0,1).toUpperCase() + loc.settings.header.slice(1, loc.settings.header.length), + title: + loc.settings.header.slice(0, 1).toUpperCase() + + loc.settings.header.slice(1, loc.settings.header.length) }; render() { return ; } -} \ No newline at end of file +} diff --git a/screen/transactions/CPFP.js b/screen/transactions/CPFP.js index 89b55e32489..2b33c9f616c 100644 --- a/screen/transactions/CPFP.js +++ b/screen/transactions/CPFP.js @@ -1,6 +1,13 @@ /* global alert */ -import React, { Component } from 'react'; -import { ActivityIndicator, View, TextInput, TouchableOpacity, Linking, Clipboard } from 'react-native'; +import React, { Component } from "react"; +import { + ActivityIndicator, + View, + TextInput, + TouchableOpacity, + Linking, + Clipboard +} from "react-native"; import { BlueSpacing20, BlueReplaceFeeSuggestions, @@ -9,37 +16,39 @@ import { BlueCard, BlueText, BlueSpacing, - BlueNavigationStyle, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class'; -import { Icon, Text } from 'react-native-elements'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from "../../class"; +import { Icon, Text } from "react-native-elements"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; /** @type {AppStorage} */ -let EV = require('../../events'); -let BlueElectrum = require('../../BlueElectrum'); -let loc = require('../../loc'); +const EV = require("../../events"); +const BlueElectrum = require("../../BlueElectrum"); +const loc = require("../../loc"); /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); +const BlueApp = require("../../BlueApp"); export default class CPFP extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(null, false), - title: 'Bump fee (CPFP)', + title: "Bump fee (CPFP)" }); constructor(props) { super(props); let txid; let wallet; - if (props.navigation.state.params) txid = props.navigation.state.params.txid; - if (props.navigation.state.params) wallet = props.navigation.state.params.wallet; + if (props.navigation.state.params) + txid = props.navigation.state.params.txid; + if (props.navigation.state.params) + wallet = props.navigation.state.params.wallet; this.state = { isLoading: true, stage: 1, txid, - wallet, + wallet }; } @@ -48,19 +57,23 @@ export default class CPFP extends Component { try { await BlueElectrum.ping(); await BlueElectrum.waitTillConnected(); - let result = await this.state.wallet.broadcastTx(this.state.txhex); + const result = await this.state.wallet.broadcastTx(this.state.txhex); if (result) { - console.log('broadcast result = ', result); + console.log("broadcast result = ", result); EV(EV.enum.REMOTE_TRANSACTIONS_COUNT_CHANGED); // someone should fetch txs this.setState({ stage: 3, isLoading: false }); this.onSuccessBroadcast(); } else { - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); this.setState({ isLoading: false }); - alert('Broadcast failed'); + alert("Broadcast failed"); } } catch (error) { - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); this.setState({ isLoading: false }); alert(error.message); } @@ -68,15 +81,17 @@ export default class CPFP extends Component { } onSuccessBroadcast() { - BlueApp.tx_metadata[this.state.newTxid] = { memo: 'Child pays for parent (CPFP)' }; + BlueApp.tx_metadata[this.state.newTxid] = { + memo: "Child pays for parent (CPFP)" + }; } async componentDidMount() { - console.log('transactions/CPFP - componentDidMount'); + console.log("transactions/CPFP - componentDidMount"); this.setState({ isLoading: true, - newFeeRate: '', - nonReplaceable: false, + newFeeRate: "", + nonReplaceable: false }); await this.checkPossibilityOfCPFP(); } @@ -86,10 +101,22 @@ export default class CPFP extends Component { return this.setState({ nonReplaceable: true, isLoading: false }); } - let tx = new HDSegwitBech32Transaction(null, this.state.txid, this.state.wallet); - if ((await tx.isToUsTransaction()) && (await tx.getRemoteConfirmationsNum()) === 0) { - let info = await tx.getInfo(); - return this.setState({ nonReplaceable: false, feeRate: info.feeRate + 1, isLoading: false, tx }); + const tx = new HDSegwitBech32Transaction( + null, + this.state.txid, + this.state.wallet + ); + if ( + (await tx.isToUsTransaction()) && + (await tx.getRemoteConfirmationsNum()) === 0 + ) { + const info = await tx.getInfo(); + return this.setState({ + nonReplaceable: false, + feeRate: info.feeRate + 1, + isLoading: false, + tx + }); // 1 sat makes a lot of difference, since sometimes because of rounding created tx's fee might be insufficient } else { return this.setState({ nonReplaceable: true, isLoading: false }); @@ -103,12 +130,16 @@ export default class CPFP extends Component { const tx = this.state.tx; this.setState({ isLoading: true }); try { - let { tx: newTx } = await tx.createCPFPbumpFee(newFeeRate); - this.setState({ stage: 2, txhex: newTx.toHex(), newTxid: newTx.getId() }); + const { tx: newTx } = await tx.createCPFPbumpFee(newFeeRate); + this.setState({ + stage: 2, + txhex: newTx.toHex(), + newTxid: newTx.getId() + }); this.setState({ isLoading: false }); } catch (_) { this.setState({ isLoading: false }); - alert('Failed: ' + _.message); + alert("Failed: " + _.message); } } } @@ -145,28 +176,30 @@ export default class CPFP extends Component { } return this.renderStage1( - 'We will create another transaction that spends your unconfirmed transaction. Total fee will be higher than original transaction\n' + - 'fee, so it should be mined faster. This is called CPFP - Child Pays For Parent.', + "We will create another transaction that spends your unconfirmed transaction. Total fee will be higher than original transaction\n" + + "fee, so it should be mined faster. This is called CPFP - Child Pays For Parent." ); } renderStage2() { return ( - - {loc.send.create.this_is_hex} + + + {loc.send.create.this_is_hex} + - Clipboard.setString(this.state.txhex)}> - Copy and broadcast later + Clipboard.setString(this.state.txhex)} + > + + Copy and broadcast later + - Linking.openURL('https://coinb.in/?verify=' + this.state.txhex)}> - Verify on coinb.in + + Linking.openURL("https://coinb.in/?verify=" + this.state.txhex) + } + > + + Verify on coinb.in + - this.broadcast()} title={loc.send.confirm.sendNow} /> + this.broadcast()} + title={loc.send.confirm.sendNow} + /> ); @@ -189,8 +251,15 @@ export default class CPFP extends Component { renderStage3() { return ( - - + + @@ -222,12 +291,19 @@ export default class CPFP extends Component { return ( - + {text} - this.setState({ newFeeRate: fee })} transactionMinimum={this.state.feeRate} /> + this.setState({ newFeeRate: fee })} + transactionMinimum={this.state.feeRate} + /> - this.createTransaction()} title="Create" /> + this.createTransaction()} + title="Create" + /> ); @@ -241,8 +317,8 @@ CPFP.propTypes = { state: PropTypes.shape({ params: PropTypes.shape({ txid: PropTypes.string, - wallet: PropTypes.object, - }), - }), - }), + wallet: PropTypes.object + }) + }) + }) }; diff --git a/screen/transactions/RBF-create.js b/screen/transactions/RBF-create.js index 8f23e9cc974..b3d3c7220fa 100644 --- a/screen/transactions/RBF-create.js +++ b/screen/transactions/RBF-create.js @@ -1,8 +1,8 @@ /** @type {AppStorage} */ /* global alert */ -import React, { Component } from 'react'; -import { TextInput, View, ActivtyIndicator } from 'react-native'; -import { FormValidationMessage } from 'react-native-elements'; +import React, { Component } from "react"; +import { TextInput, View, ActivtyIndicator } from "react-native"; +import { FormValidationMessage } from "react-native-elements"; import { BlueLoading, BlueSpacing20, @@ -11,42 +11,44 @@ import { BlueCard, BlueText, BlueSpacing, - BlueNavigationStyle, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; -const bitcoinjs = require('bitcoinjs-lib'); -let BigNumber = require('bignumber.js'); -let BlueApp = require('../../BlueApp'); + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; + +const bitcoinjs = require("bitcoinjs-lib"); +const BigNumber = require("bignumber.js"); +const BlueApp = require("../../BlueApp"); export default class SendCreate extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(null, false), - title: 'Create RBF', + title: "Create RBF" }); constructor(props) { super(props); - console.log('send/create constructor'); + console.log("send/create constructor"); if (!props.navigation.state.params.feeDelta) { - props.navigation.state.params.feeDelta = '0'; + props.navigation.state.params.feeDelta = "0"; } this.state = { isLoading: true, feeDelta: props.navigation.state.params.feeDelta, - newDestinationAddress: props.navigation.state.params.newDestinationAddress, + newDestinationAddress: + props.navigation.state.params.newDestinationAddress, txid: props.navigation.state.params.txid, sourceTx: props.navigation.state.params.sourceTx, - fromWallet: props.navigation.state.params.sourceWallet, + fromWallet: props.navigation.state.params.sourceWallet }; } async componentDidMount() { - console.log('RBF-create - componentDidMount'); + console.log("RBF-create - componentDidMount"); - let utxo = []; + const utxo = []; let lastSequence = 0; let totalInputAmountSatoshi = 0; - for (let input of this.state.sourceTx.inputs) { + for (const input of this.state.sourceTx.inputs) { if (input.sequence > lastSequence) { lastSequence = input.sequence; } @@ -56,7 +58,7 @@ export default class SendCreate extends Component { utxo.push({ tx_hash: input.prev_hash, tx_output_n: input.output_index, - value: input.output_value, + value: input.output_value }); } @@ -64,12 +66,12 @@ export default class SendCreate extends Component { if (lastSequence === bitcoinjs.Transaction.DEFAULT_SEQUENCE) { return this.setState({ isLoading: false, - nonReplaceable: true, + nonReplaceable: true }); // lastSequence = 1 } - let txMetadata = BlueApp.tx_metadata[this.state.txid]; + const txMetadata = BlueApp.tx_metadata[this.state.txid]; if (txMetadata) { if (txMetadata.last_sequence) { lastSequence = Math.max(lastSequence, txMetadata.last_sequence); @@ -81,7 +83,7 @@ export default class SendCreate extends Component { let changeAddress; let transferAmount; let totalOutputAmountSatoshi = 0; - for (let o of this.state.sourceTx.outputs) { + for (const o of this.state.sourceTx.outputs) { totalOutputAmountSatoshi += o.value; if (o.addresses[0] === this.state.fromWallet.getAddress()) { // change @@ -91,20 +93,22 @@ export default class SendCreate extends Component { transferAmount = transferAmount.dividedBy(100000000).toString(10); } } - let oldFee = new BigNumber(totalInputAmountSatoshi - totalOutputAmountSatoshi); + let oldFee = new BigNumber( + totalInputAmountSatoshi - totalOutputAmountSatoshi + ); oldFee = parseFloat(oldFee.dividedBy(100000000).toString(10)); - console.log('changeAddress = ', changeAddress); - console.log('utxo', utxo); - console.log('lastSequence', lastSequence); - console.log('totalInputAmountSatoshi', totalInputAmountSatoshi); - console.log('totalOutputAmountSatoshi', totalOutputAmountSatoshi); - console.log('transferAmount', transferAmount); - console.log('oldFee', oldFee); + console.log("changeAddress = ", changeAddress); + console.log("utxo", utxo); + console.log("lastSequence", lastSequence); + console.log("totalInputAmountSatoshi", totalInputAmountSatoshi); + console.log("totalOutputAmountSatoshi", totalOutputAmountSatoshi); + console.log("transferAmount", transferAmount); + console.log("oldFee", oldFee); let newFee = new BigNumber(oldFee); newFee = newFee.plus(this.state.feeDelta).toString(10); - console.log('new Fee', newFee); + console.log("new Fee", newFee); // creating TX @@ -112,47 +116,57 @@ export default class SendCreate extends Component { // more responsive let tx; try { - tx = this.state.fromWallet.createTx(utxo, transferAmount, newFee, this.state.newDestinationAddress, false, lastSequence); + tx = this.state.fromWallet.createTx( + utxo, + transferAmount, + newFee, + this.state.newDestinationAddress, + false, + lastSequence + ); BlueApp.tx_metadata[this.state.txid] = txMetadata || {}; - BlueApp.tx_metadata[this.state.txid]['last_sequence'] = lastSequence; + BlueApp.tx_metadata[this.state.txid]["last_sequence"] = lastSequence; // in case new TX get confirmed, we must save metadata under new txid - let bitcoin = bitcoinjs; - let txDecoded = bitcoin.Transaction.fromHex(tx); - let txid = txDecoded.getId(); + const bitcoin = bitcoinjs; + const txDecoded = bitcoin.Transaction.fromHex(tx); + const txid = txDecoded.getId(); BlueApp.tx_metadata[txid] = BlueApp.tx_metadata[this.state.txid]; - BlueApp.tx_metadata[txid]['txhex'] = tx; + BlueApp.tx_metadata[txid]["txhex"] = tx; // BlueApp.saveToDisk(); - console.log('BlueApp.txMetadata[this.state.txid]', BlueApp.tx_metadata[this.state.txid]); + console.log( + "BlueApp.txMetadata[this.state.txid]", + BlueApp.tx_metadata[this.state.txid] + ); } catch (err) { console.log(err); return this.setState({ isError: true, - errorMessage: JSON.stringify(err.message), + errorMessage: JSON.stringify(err.message) }); } let newFeeSatoshi = new BigNumber(newFee); newFeeSatoshi = parseInt(newFeeSatoshi.multipliedBy(100000000)); - let satoshiPerByte = Math.round(newFeeSatoshi / (tx.length / 2)); + const satoshiPerByte = Math.round(newFeeSatoshi / (tx.length / 2)); this.setState({ isLoading: false, size: Math.round(tx.length / 2), tx, satoshiPerByte: satoshiPerByte, amount: transferAmount, - fee: newFee, + fee: newFee }); }, 10); } async broadcast() { this.setState({ isLoading: true }, async () => { - console.log('broadcasting', this.state.tx); + console.log("broadcasting", this.state.tx); let result = await this.state.fromWallet.broadcastTx(this.state.tx); - console.log('broadcast result = ', result); - if (typeof result === 'string') { + console.log("broadcast result = ", result); + if (typeof result === "string") { try { result = JSON.parse(result); } catch (_) { @@ -164,7 +178,7 @@ export default class SendCreate extends Component { this.setState({ isLoading: false }); } else { alert(JSON.stringify(result.result || result.txid)); - this.props.navigation.navigate('TransactionStatus'); + this.props.navigation.navigate("TransactionStatus"); } }); } @@ -174,11 +188,21 @@ export default class SendCreate extends Component { return ( - - Error creating transaction. Invalid address or send amount? - {this.state.errorMessage} + + + Error creating transaction. Invalid address or send amount? + + + {this.state.errorMessage} + - this.props.navigation.goBack()} title="Go back" /> + this.props.navigation.goBack()} + title="Go back" + /> ); } @@ -190,8 +214,14 @@ export default class SendCreate extends Component { if (this.state.nonReplaceable) { return ( - - + + This transaction is not replaceable @@ -202,15 +232,21 @@ export default class SendCreate extends Component { return ( - - This is transaction hex, signed and ready to be broadcast to the network. Continue? + + + This is transaction hex, signed and ready to be broadcast to the + network. Continue? + - To: {this.state.newDestinationAddress} + + To: {this.state.newDestinationAddress} + Amount: {this.state.amount} BTC Fee: {this.state.fee} BTC TX size: {this.state.size} Bytes @@ -229,7 +267,11 @@ export default class SendCreate extends Component { {this.state.isLoading ? ( ) : ( - this.broadcast()} title="Broadcast" /> + this.broadcast()} + title="Broadcast" + /> )} ); @@ -248,8 +290,8 @@ SendCreate.propTypes = { newDestinationAddress: PropTypes.string, txid: PropTypes.string, sourceTx: PropTypes.object, - sourceWallet: PropTypes.object, - }), - }), - }), + sourceWallet: PropTypes.object + }) + }) + }) }; diff --git a/screen/transactions/RBF.js b/screen/transactions/RBF.js index b8c2b69c260..7a741b801ca 100644 --- a/screen/transactions/RBF.js +++ b/screen/transactions/RBF.js @@ -1,26 +1,35 @@ -import React, { Component } from 'react'; -import { ActivityIndicator, View, TextInput } from 'react-native'; -import { BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueText, BlueSpacing, BlueNavigationStyle } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { SegwitBech32Wallet } from '../../class'; +import React, { Component } from "react"; +import { ActivityIndicator, View, TextInput } from "react-native"; +import { + BlueSpacing20, + BlueButton, + SafeBlueArea, + BlueCard, + BlueText, + BlueSpacing, + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { SegwitBech32Wallet } from "../../class"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); +const BlueApp = require("../../BlueApp"); export default class RBF extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(null, false), - title: 'RBF', + title: "RBF" }); constructor(props) { super(props); let txid; - if (props.navigation.state.params) txid = props.navigation.state.params.txid; + if (props.navigation.state.params) + txid = props.navigation.state.params.txid; let sourceWallet; let sourceTx; - for (let w of BlueApp.getWallets()) { - for (let t of w.getTransactions()) { + for (const w of BlueApp.getWallets()) { + for (const t of w.getTransactions()) { if (t.hash === txid) { // found our source wallet sourceWallet = w; @@ -32,7 +41,7 @@ export default class RBF extends Component { let destinationAddress; - for (let o of sourceTx.outputs) { + for (const o of sourceTx.outputs) { if (!o.addresses && o.script) { // probably bech32 output, so we need to decode address o.addresses = [SegwitBech32Wallet.scriptPubKeyToAddress(o.script)]; @@ -44,16 +53,16 @@ export default class RBF extends Component { } else { // DESTINATION address - destinationAddress = (o.addresses && o.addresses[0]) || ''; - console.log('dest = ', destinationAddress); + destinationAddress = (o.addresses && o.addresses[0]) || ""; + console.log("dest = ", destinationAddress); } } - if (!destinationAddress || sourceWallet.type === 'legacy') { + if (!destinationAddress || sourceWallet.type === "legacy") { // for now I'm too lazy to add RBF support for legacy addresses this.state = { isLoading: false, - nonReplaceable: true, + nonReplaceable: true }; return; } @@ -64,27 +73,27 @@ export default class RBF extends Component { sourceTx, sourceWallet, newDestinationAddress: destinationAddress, - feeDelta: '', + feeDelta: "" }; } async componentDidMount() { - let startTime = Date.now(); - console.log('transactions/RBF - componentDidMount'); + const startTime = Date.now(); + console.log("transactions/RBF - componentDidMount"); this.setState({ - isLoading: false, + isLoading: false }); - let endTime = Date.now(); - console.log('componentDidMount took', (endTime - startTime) / 1000, 'sec'); + const endTime = Date.now(); + console.log("componentDidMount took", (endTime - startTime) / 1000, "sec"); } createTransaction() { - this.props.navigation.navigate('CreateRBF', { + this.props.navigation.navigate("CreateRBF", { feeDelta: this.state.feeDelta, newDestinationAddress: this.state.newDestinationAddress, txid: this.state.txid, sourceTx: this.state.sourceTx, - sourceWallet: this.state.sourceWallet, + sourceWallet: this.state.sourceWallet }); } @@ -108,7 +117,10 @@ export default class RBF extends Component { This transaction is not replaceable - this.props.navigation.goBack()} title="Back" /> + this.props.navigation.goBack()} + title="Back" + /> ); } @@ -116,8 +128,13 @@ export default class RBF extends Component { if (!this.state.sourceWallet.getAddress) { return ( - System error: Source wallet not found (this should never happen) - this.props.navigation.goBack()} title="Back" /> + + System error: Source wallet not found (this should never happen) + + this.props.navigation.goBack()} + title="Back" + /> ); } @@ -125,59 +142,78 @@ export default class RBF extends Component { return ( - - RBF allows you to increase fee on already sent but not confirmed transaction, thus speeding up mining + + + RBF allows you to increase fee on already sent but not confirmed + transaction, thus speeding up mining + - From wallet '{this.state.sourceWallet.getLabel()}' ({this.state.sourceWallet.getAddress()}) + From wallet '{this.state.sourceWallet.getLabel()}' ( + {this.state.sourceWallet.getAddress()}) this.setState({ newDestinationAddress: text })} - placeholder={'receiver address here'} + onChangeText={text => + this.setState({ newDestinationAddress: text }) + } + placeholder={"receiver address here"} placeholderTextColor={BlueApp.settings.alternativeTextColor} value={this.state.newDestinationAddress} - style={{ flex: 1, minHeight: 33, marginHorizontal: 8, color: BlueApp.settings.foregroundColor }} + style={{ + flex: 1, + minHeight: 33, + marginHorizontal: 8, + color: BlueApp.settings.foregroundColor + }} /> this.setState({ feeDelta: text })} - keyboardType={'numeric'} - placeholder={'fee to add (in BTC)'} + keyboardType={"numeric"} + placeholder={"fee to add (in BTC)"} placeholderTextColor={BlueApp.settings.alternativeTextColor} - value={this.state.feeDelta + ''} - style={{ flex: 1, minHeight: 33, marginHorizontal: 8, color: BlueApp.settings.foregroundColor }} + value={this.state.feeDelta + ""} + style={{ + flex: 1, + minHeight: 33, + marginHorizontal: 8, + color: BlueApp.settings.foregroundColor + }} /> @@ -195,8 +231,8 @@ RBF.propTypes = { navigate: PropTypes.func, state: PropTypes.shape({ params: PropTypes.shape({ - txid: PropTypes.string, - }), - }), - }), + txid: PropTypes.string + }) + }) + }) }; diff --git a/screen/transactions/RBFBumpFee.js b/screen/transactions/RBFBumpFee.js index 0c55a285dc8..3cea1790f6a 100644 --- a/screen/transactions/RBFBumpFee.js +++ b/screen/transactions/RBFBumpFee.js @@ -1,25 +1,30 @@ /* global alert */ -import React from 'react'; -import { ActivityIndicator, View } from 'react-native'; -import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class'; -import CPFP from './CPFP'; +import React from "react"; +import { ActivityIndicator, View } from "react-native"; +import { + BlueSpacing20, + SafeBlueArea, + BlueText, + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from "../../class"; +import CPFP from "./CPFP"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); +const BlueApp = require("../../BlueApp"); export default class RBFBumpFee extends CPFP { static navigationOptions = () => ({ ...BlueNavigationStyle(null, false), - title: 'Bump fee (RBF)', + title: "Bump fee (RBF)" }); async componentDidMount() { - console.log('transactions/RBFBumpFee - componentDidMount'); + console.log("transactions/RBFBumpFee - componentDidMount"); this.setState({ isLoading: true, - newFeeRate: '', - nonReplaceable: false, + newFeeRate: "", + nonReplaceable: false }); await this.checkPossibilityOfRBFBumpFee(); } @@ -29,10 +34,23 @@ export default class RBFBumpFee extends CPFP { return this.setState({ nonReplaceable: true, isLoading: false }); } - let tx = new HDSegwitBech32Transaction(null, this.state.txid, this.state.wallet); - if ((await tx.isOurTransaction()) && (await tx.getRemoteConfirmationsNum()) === 0 && (await tx.isSequenceReplaceable())) { - let info = await tx.getInfo(); - return this.setState({ nonReplaceable: false, feeRate: info.feeRate + 1, isLoading: false, tx }); + const tx = new HDSegwitBech32Transaction( + null, + this.state.txid, + this.state.wallet + ); + if ( + (await tx.isOurTransaction()) && + (await tx.getRemoteConfirmationsNum()) === 0 && + (await tx.isSequenceReplaceable()) + ) { + const info = await tx.getInfo(); + return this.setState({ + nonReplaceable: false, + feeRate: info.feeRate + 1, + isLoading: false, + tx + }); // 1 sat makes a lot of difference, since sometimes because of rounding created tx's fee might be insufficient } else { return this.setState({ nonReplaceable: true, isLoading: false }); @@ -46,12 +64,16 @@ export default class RBFBumpFee extends CPFP { const tx = this.state.tx; this.setState({ isLoading: true }); try { - let { tx: newTx } = await tx.createRBFbumpFee(newFeeRate); - this.setState({ stage: 2, txhex: newTx.toHex(), newTxid: newTx.getId() }); + const { tx: newTx } = await tx.createRBFbumpFee(newFeeRate); + this.setState({ + stage: 2, + txhex: newTx.toHex(), + newTxid: newTx.getId() + }); this.setState({ isLoading: false }); } catch (_) { this.setState({ isLoading: false }); - alert('Failed: ' + _.message); + alert("Failed: " + _.message); } } } @@ -59,7 +81,8 @@ export default class RBFBumpFee extends CPFP { onSuccessBroadcast() { // porting memo from old tx: if (BlueApp.tx_metadata[this.state.txid]) { - BlueApp.tx_metadata[this.state.newTxid] = BlueApp.tx_metadata[this.state.txid]; + BlueApp.tx_metadata[this.state.newTxid] = + BlueApp.tx_metadata[this.state.txid]; } } @@ -95,7 +118,7 @@ export default class RBFBumpFee extends CPFP { } return this.renderStage1( - 'We will replace this transaction with the one with higher fees, so it should be mined faster. This is called RBF - Replace By Fee.', + "We will replace this transaction with the one with higher fees, so it should be mined faster. This is called RBF - Replace By Fee." ); } } @@ -107,8 +130,8 @@ RBFBumpFee.propTypes = { state: PropTypes.shape({ params: PropTypes.shape({ txid: PropTypes.string, - wallet: PropTypes.object, - }), - }), - }), + wallet: PropTypes.object + }) + }) + }) }; diff --git a/screen/transactions/RBFCancel.js b/screen/transactions/RBFCancel.js index 3222b3a4717..0d4bee3d71d 100644 --- a/screen/transactions/RBFCancel.js +++ b/screen/transactions/RBFCancel.js @@ -1,25 +1,30 @@ /* global alert */ -import React from 'react'; -import { ActivityIndicator, View } from 'react-native'; -import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class'; -import CPFP from './CPFP'; +import React from "react"; +import { ActivityIndicator, View } from "react-native"; +import { + BlueSpacing20, + SafeBlueArea, + BlueText, + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from "../../class"; +import CPFP from "./CPFP"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); +const BlueApp = require("../../BlueApp"); export default class RBFCancel extends CPFP { static navigationOptions = () => ({ ...BlueNavigationStyle(null, false), - title: 'Cancel this transaction (RBF)', + title: "Cancel this transaction (RBF)" }); async componentDidMount() { - console.log('transactions/RBFCancel - componentDidMount'); + console.log("transactions/RBFCancel - componentDidMount"); this.setState({ isLoading: true, - newFeeRate: '', - nonReplaceable: false, + newFeeRate: "", + nonReplaceable: false }); await this.checkPossibilityOfRBFCancel(); } @@ -29,16 +34,25 @@ export default class RBFCancel extends CPFP { return this.setState({ nonReplaceable: true, isLoading: false }); } - let tx = new HDSegwitBech32Transaction(null, this.state.txid, this.state.wallet); + const tx = new HDSegwitBech32Transaction( + null, + this.state.txid, + this.state.wallet + ); if ( (await tx.isOurTransaction()) && (await tx.getRemoteConfirmationsNum()) === 0 && (await tx.isSequenceReplaceable()) && (await tx.canCancelTx()) ) { - let info = await tx.getInfo(); + const info = await tx.getInfo(); console.log({ info }); - return this.setState({ nonReplaceable: false, feeRate: info.feeRate + 1, isLoading: false, tx }); + return this.setState({ + nonReplaceable: false, + feeRate: info.feeRate + 1, + isLoading: false, + tx + }); // 1 sat makes a lot of difference, since sometimes because of rounding created tx's fee might be insufficient } else { return this.setState({ nonReplaceable: true, isLoading: false }); @@ -52,25 +66,31 @@ export default class RBFCancel extends CPFP { const tx = this.state.tx; this.setState({ isLoading: true }); try { - let { tx: newTx } = await tx.createRBFcancelTx(newFeeRate); - this.setState({ stage: 2, txhex: newTx.toHex(), newTxid: newTx.getId() }); + const { tx: newTx } = await tx.createRBFcancelTx(newFeeRate); + this.setState({ + stage: 2, + txhex: newTx.toHex(), + newTxid: newTx.getId() + }); this.setState({ isLoading: false }); } catch (_) { this.setState({ isLoading: false }); - alert('Failed: ' + _.message); + alert("Failed: " + _.message); } } } onSuccessBroadcast() { // porting metadata, if any - BlueApp.tx_metadata[this.state.newTxid] = BlueApp.tx_metadata[this.state.txid] || {}; + BlueApp.tx_metadata[this.state.newTxid] = + BlueApp.tx_metadata[this.state.txid] || {}; // porting tx memo - if (BlueApp.tx_metadata[this.state.newTxid]['memo']) { - BlueApp.tx_metadata[this.state.newTxid]['memo'] = 'Cancelled: ' + BlueApp.tx_metadata[this.state.newTxid]['memo']; + if (BlueApp.tx_metadata[this.state.newTxid]["memo"]) { + BlueApp.tx_metadata[this.state.newTxid]["memo"] = + "Cancelled: " + BlueApp.tx_metadata[this.state.newTxid]["memo"]; } else { - BlueApp.tx_metadata[this.state.newTxid]['memo'] = 'Cancelled transaction'; + BlueApp.tx_metadata[this.state.newTxid]["memo"] = "Cancelled transaction"; } } @@ -106,7 +126,7 @@ export default class RBFCancel extends CPFP { } return this.renderStage1( - 'We will replace this transaction with the one that pays you and has higher fees. This effectively cancels transaction. This is called RBF - Replace By Fee.', + "We will replace this transaction with the one that pays you and has higher fees. This effectively cancels transaction. This is called RBF - Replace By Fee." ); } } @@ -118,8 +138,8 @@ RBFCancel.propTypes = { state: PropTypes.shape({ params: PropTypes.shape({ txid: PropTypes.string, - wallet: PropTypes.object, - }), - }), - }), + wallet: PropTypes.object + }) + }) + }) }; diff --git a/screen/transactions/details.js b/screen/transactions/details.js index ede26dbb563..541d52799e3 100644 --- a/screen/transactions/details.js +++ b/screen/transactions/details.js @@ -1,5 +1,5 @@ -import React, { Component } from 'react'; -import { View, ScrollView, TouchableOpacity, Linking } from 'react-native'; +import React, { Component } from "react"; +import { View, ScrollView, TouchableOpacity, Linking } from "react-native"; import { SafeBlueArea, BlueCard, @@ -8,21 +8,21 @@ import { BlueLoading, BlueSpacing20, BlueCopyToClipboardButton, - BlueNavigationStyle, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); -const dayjs = require('dayjs'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); +const dayjs = require("dayjs"); function onlyUnique(value, index, self) { return self.indexOf(value) === index; } function arrDiff(a1, a2) { - let ret = []; - for (let v of a2) { + const ret = []; + for (const v of a2) { if (a1.indexOf(v) === -1) { ret.push(v); } @@ -33,33 +33,34 @@ function arrDiff(a1, a2) { export default class TransactionsDetails extends Component { static navigationOptions = () => ({ ...BlueNavigationStyle(), - title: loc.transactions.details.title, + title: loc.transactions.details.title }); constructor(props) { super(props); - let hash = props.navigation.state.params.hash; + const hash = props.navigation.state.params.hash; let foundTx = {}; let from = []; let to = []; - for (let tx of BlueApp.getTransactions()) { + for (const tx of BlueApp.getTransactions()) { if (tx.hash === hash) { foundTx = tx; - for (let input of foundTx.inputs) { + for (const input of foundTx.inputs) { from = from.concat(input.addresses); } - for (let output of foundTx.outputs) { + for (const output of foundTx.outputs) { if (output.addresses) to = to.concat(output.addresses); - if (output.scriptPubKey && output.scriptPubKey.addresses) to = to.concat(output.scriptPubKey.addresses); + if (output.scriptPubKey && output.scriptPubKey.addresses) + to = to.concat(output.scriptPubKey.addresses); } } } let wallet = false; - for (let w of BlueApp.getWallets()) { - for (let t of w.getTransactions()) { + for (const w of BlueApp.getWallets()) { + for (const t of w.getTransactions()) { if (t.hash === hash) { - console.log('tx', hash, 'belongs to', w.getLabel()); + console.log("tx", hash, "belongs to", w.getLabel()); wallet = w; } } @@ -69,32 +70,34 @@ export default class TransactionsDetails extends Component { tx: foundTx, from, to, - wallet, + wallet }; } async componentDidMount() { - console.log('transactions/details - componentDidMount'); + console.log("transactions/details - componentDidMount"); this.setState({ - isLoading: false, + isLoading: false }); } render() { - if (this.state.isLoading || !this.state.hasOwnProperty('tx')) { + if (this.state.isLoading || !this.state.hasOwnProperty("tx")) { return ; } return ( - + {(() => { if (BlueApp.tx_metadata[this.state.tx.hash]) { - if (BlueApp.tx_metadata[this.state.tx.hash]['memo']) { + if (BlueApp.tx_metadata[this.state.tx.hash]["memo"]) { return ( - {BlueApp.tx_metadata[this.state.tx.hash]['memo']} + + {BlueApp.tx_metadata[this.state.tx.hash]["memo"]} + ); @@ -102,42 +105,133 @@ export default class TransactionsDetails extends Component { } })()} - {this.state.hasOwnProperty('from') && ( + {this.state.hasOwnProperty("from") && ( - - {loc.transactions.details.from} - + + + {loc.transactions.details.from} + + - {this.state.from.filter(onlyUnique).join(', ')} + + {this.state.from.filter(onlyUnique).join(", ")} + )} - {this.state.hasOwnProperty('to') && ( + {this.state.hasOwnProperty("to") && ( - - {loc.transactions.details.to} - + + + {loc.transactions.details.to} + + - - {arrDiff(this.state.from, this.state.to.filter(onlyUnique)).join(', ')} + + {arrDiff( + this.state.from, + this.state.to.filter(onlyUnique) + ).join(", ")} )} - {this.state.tx.hasOwnProperty('fee') && ( + {this.state.tx.hasOwnProperty("fee") && ( - {loc.send.create.fee} - {this.state.tx.fee + ' sats'} + + {loc.send.create.fee} + + + {this.state.tx.fee + " sats"} + )} - {this.state.tx.hasOwnProperty('txid') && ( + {this.state.tx.hasOwnProperty("txid") && ( - - Transaction ID - + + + Transaction ID + + - {this.state.tx.txid} + + {this.state.tx.txid} + { const url = `http://explorer.veles.network/tx/${this.state.tx.txid}`; @@ -148,38 +242,111 @@ export default class TransactionsDetails extends Component { }); }} > - {loc.transactions.details.show_in_block_explorer} + + {loc.transactions.details.show_in_block_explorer} + )} - {this.state.tx.hasOwnProperty('received') && ( + {this.state.tx.hasOwnProperty("received") && ( - Date & time - {dayjs(this.state.tx.received).format('MM/DD/YYYY h:mm A')} + + Date & time + + + {dayjs(this.state.tx.received).format("MM/DD/YYYY h:mm A")} + )} - {this.state.tx.hasOwnProperty('block_height') && this.state.tx.block_height > 0 && ( - - Block Height - {this.state.tx.block_height} - - )} + {this.state.tx.hasOwnProperty("block_height") && + this.state.tx.block_height > 0 && ( + + + Block Height + + + {this.state.tx.block_height} + + + )} - {this.state.tx.hasOwnProperty('inputs') && ( + {this.state.tx.hasOwnProperty("inputs") && ( - Inputs - {this.state.tx.inputs.length} + + Inputs + + + {this.state.tx.inputs.length} + )} - {this.state.tx.hasOwnProperty('outputs') && this.state.tx.outputs.length > 0 && ( - - Outputs - {this.state.tx.outputs.length} - - )} + {this.state.tx.hasOwnProperty("outputs") && + this.state.tx.outputs.length > 0 && ( + + + Outputs + + + {this.state.tx.outputs.length} + + + )} @@ -193,8 +360,8 @@ TransactionsDetails.propTypes = { navigate: PropTypes.func, state: PropTypes.shape({ params: PropTypes.shape({ - hash: PropTypes.string, - }), - }), - }), + hash: PropTypes.string + }) + }) + }) }; diff --git a/screen/transactions/transactionStatus.js b/screen/transactions/transactionStatus.js index 0fa7cec6eba..9429120e8bd 100644 --- a/screen/transactions/transactionStatus.js +++ b/screen/transactions/transactionStatus.js @@ -1,5 +1,5 @@ -import React, { Component } from 'react'; -import { View, ActivityIndicator, Text, TouchableOpacity } from 'react-native'; +import React, { Component } from "react"; +import { View, ActivityIndicator, Text, TouchableOpacity } from "react-native"; import { BlueButton, SafeBlueArea, @@ -10,52 +10,52 @@ import { BlueText, BlueLoading, BlueSpacing20, - BlueNavigationStyle, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from '../../class'; -import { BitcoinUnit } from '../../models/bitcoinUnits'; -import { Icon } from 'react-native-elements'; -import Handoff from 'react-native-handoff'; + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { HDSegwitBech32Transaction, HDSegwitBech32Wallet } from "../../class"; +import { BitcoinUnit } from "../../models/bitcoinUnits"; +import { Icon } from "react-native-elements"; +import Handoff from "react-native-handoff"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); const buttonStatus = Object.freeze({ possible: 1, unknown: 2, - notPossible: 3, + notPossible: 3 }); export default class TransactionsStatus extends Component { static navigationOptions = () => ({ - ...BlueNavigationStyle(), + ...BlueNavigationStyle() }); constructor(props) { super(props); - let hash = props.navigation.state.params.hash; - let label = props.navigation.state.params.walletLabel; + const hash = props.navigation.state.params.hash; + const label = props.navigation.state.params.walletLabel; let foundTx = {}; let from = []; let to = []; - for (let tx of BlueApp.getTransactions()) { + for (const tx of BlueApp.getTransactions()) { if (tx.hash === hash && tx.walletLabel === label) { foundTx = tx; - for (let input of foundTx.inputs) { + for (const input of foundTx.inputs) { from = from.concat(input.addresses); } - for (let output of foundTx.outputs) { + for (const output of foundTx.outputs) { if (output.addresses) to = to.concat(output.addresses); - if (output.scriptPubKey && output.scriptPubKey.addresses) to = to.concat(output.scriptPubKey.addresses); + if (output.scriptPubKey && output.scriptPubKey.addresses) + to = to.concat(output.scriptPubKey.addresses); } } } let wallet = false; - for (let w of BlueApp.getWallets()) { - if (w.getLabel() === foundTx.walletLabel) - wallet = w; + for (const w of BlueApp.getWallets()) { + if (w.getLabel() === foundTx.walletLabel) wallet = w; } this.state = { @@ -66,14 +66,14 @@ export default class TransactionsStatus extends Component { wallet, isCPFPpossible: buttonStatus.unknown, isRBFBumpFeePossible: buttonStatus.unknown, - isRBFCancelPossible: buttonStatus.unknown, + isRBFCancelPossible: buttonStatus.unknown }; } async componentDidMount() { - console.log('transactions/details - componentDidMount'); + console.log("transactions/details - componentDidMount"); this.setState({ - isLoading: false, + isLoading: false }); try { @@ -84,7 +84,7 @@ export default class TransactionsStatus extends Component { this.setState({ isCPFPpossible: buttonStatus.notPossible, isRBFBumpFeePossible: buttonStatus.notPossible, - isRBFCancelPossible: buttonStatus.notPossible, + isRBFCancelPossible: buttonStatus.notPossible }); } } @@ -94,8 +94,15 @@ export default class TransactionsStatus extends Component { return this.setState({ isCPFPpossible: buttonStatus.notPossible }); } - let tx = new HDSegwitBech32Transaction(null, this.state.tx.hash, this.state.wallet); - if ((await tx.isToUsTransaction()) && (await tx.getRemoteConfirmationsNum()) === 0) { + const tx = new HDSegwitBech32Transaction( + null, + this.state.tx.hash, + this.state.wallet + ); + if ( + (await tx.isToUsTransaction()) && + (await tx.getRemoteConfirmationsNum()) === 0 + ) { return this.setState({ isCPFPpossible: buttonStatus.possible }); } else { return this.setState({ isCPFPpossible: buttonStatus.notPossible }); @@ -107,8 +114,16 @@ export default class TransactionsStatus extends Component { return this.setState({ isRBFBumpFeePossible: buttonStatus.notPossible }); } - let tx = new HDSegwitBech32Transaction(null, this.state.tx.hash, this.state.wallet); - if ((await tx.isOurTransaction()) && (await tx.getRemoteConfirmationsNum()) === 0 && (await tx.isSequenceReplaceable())) { + const tx = new HDSegwitBech32Transaction( + null, + this.state.tx.hash, + this.state.wallet + ); + if ( + (await tx.isOurTransaction()) && + (await tx.getRemoteConfirmationsNum()) === 0 && + (await tx.isSequenceReplaceable()) + ) { return this.setState({ isRBFBumpFeePossible: buttonStatus.possible }); } else { return this.setState({ isRBFBumpFeePossible: buttonStatus.notPossible }); @@ -120,7 +135,11 @@ export default class TransactionsStatus extends Component { return this.setState({ isRBFCancelPossible: buttonStatus.notPossible }); } - let tx = new HDSegwitBech32Transaction(null, this.state.tx.hash, this.state.wallet); + const tx = new HDSegwitBech32Transaction( + null, + this.state.tx.hash, + this.state.wallet + ); if ( (await tx.isOurTransaction()) && (await tx.getRemoteConfirmationsNum()) === 0 && @@ -142,62 +161,82 @@ export default class TransactionsStatus extends Component { } else if (walletPreviousPreferredUnit === BitcoinUnit.SATS) { wallet.preferredBalanceUnit = BitcoinUnit.BTC; walletPreviousPreferredUnit = BitcoinUnit.SATS; - } else { + } else { wallet.preferredBalanceUnit = BitcoinUnit.BTC; walletPreviousPreferredUnit = BitcoinUnit.BTC; } // this.state.wallet.preferredBalanceUnit = wallet.preferredBalanceUnit; this.setState({ state: this.state }); - }; + } render() { - if (this.state.isLoading || !this.state.hasOwnProperty('tx')) { + if (this.state.isLoading || !this.state.hasOwnProperty("tx")) { return ; } return ( - + - + - this.changeWalletBalanceUnit()} - > - - - {loc.formatBalanceWithoutSuffix(this.state.tx.value, this.state.wallet.preferredBalanceUnit, true)}{' '} - {this.state.wallet.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && ( - {this.state.wallet.preferredBalanceUnit} - )} - - - + this.changeWalletBalanceUnit()}> + > + + + {loc.formatBalanceWithoutSuffix( + this.state.tx.value, + this.state.wallet.preferredBalanceUnit, + true + )}{" "} + {this.state.wallet.preferredBalanceUnit !== + BitcoinUnit.LOCAL_CURRENCY && ( + + {this.state.wallet.preferredBalanceUnit} + + )} + + + {(() => { if (BlueApp.tx_metadata[this.state.tx.hash]) { - if (BlueApp.tx_metadata[this.state.tx.hash]['memo']) { + if (BlueApp.tx_metadata[this.state.tx.hash]["memo"]) { return ( - - {BlueApp.tx_metadata[this.state.tx.hash]['memo']} - - - ); - } - } - else { - return ( - - {this.state.tx.walletLabel} + + + {BlueApp.tx_metadata[this.state.tx.hash]["memo"]} + ); } + } else { + return ( + + + {this.state.tx.walletLabel} + + + + ); } - )()} + })()} - + {(() => { @@ -249,12 +293,26 @@ export default class TransactionsStatus extends Component { - {this.state.tx.hasOwnProperty('fee') && ( + {this.state.tx.hasOwnProperty("fee") && ( - - {loc.send.create.fee.toLowerCase()}{' '} - {loc.formatBalanceWithoutSuffix(this.state.tx.fee, this.state.wallet.preferredBalanceUnit, true)}{' '} - {this.state.wallet.preferredBalanceUnit !== BitcoinUnit.LOCAL_CURRENCY && this.state.wallet.preferredBalanceUnit} + + {loc.send.create.fee.toLowerCase()}{" "} + {loc.formatBalanceWithoutSuffix( + this.state.tx.fee, + this.state.wallet.preferredBalanceUnit, + true + )}{" "} + {this.state.wallet.preferredBalanceUnit !== + BitcoinUnit.LOCAL_CURRENCY && + this.state.wallet.preferredBalanceUnit} )} @@ -265,26 +323,35 @@ export default class TransactionsStatus extends Component { backgroundColor: BlueApp.settings.buttonBackgroundColor, width: 120, height: 25, - alignSelf: 'center', - alignItems: 'center', - justifyContent: 'center', + alignSelf: "center", + alignItems: "center", + justifyContent: "center" }} > - + {this.state.tx.confirmations} confirmations - + {(() => { - if (this.state.tx.confirmations === 0 && this.state.wallet && this.state.wallet.allowRBF()) { + if ( + this.state.tx.confirmations === 0 && + this.state.wallet && + this.state.wallet.allowRBF() + ) { return ( - this.props.navigation.navigate('RBF', { - txid: this.state.tx.hash, + this.props.navigation.navigate("RBF", { + txid: this.state.tx.hash }) } title="Replace-By-Fee (RBF)" @@ -308,9 +375,9 @@ export default class TransactionsStatus extends Component { - this.props.navigation.navigate('CPFP', { + this.props.navigation.navigate("CPFP", { txid: this.state.tx.hash, - wallet: this.state.wallet, + wallet: this.state.wallet }) } title="Bump Fee" @@ -329,14 +396,16 @@ export default class TransactionsStatus extends Component { ); - } else if (this.state.isRBFBumpFeePossible === buttonStatus.possible) { + } else if ( + this.state.isRBFBumpFeePossible === buttonStatus.possible + ) { return ( - this.props.navigation.navigate('RBFBumpFee', { + this.props.navigation.navigate("RBFBumpFee", { txid: this.state.tx.hash, - wallet: this.state.wallet, + wallet: this.state.wallet }) } title="Bump Fee" @@ -352,20 +421,27 @@ export default class TransactionsStatus extends Component { ); - } else if (this.state.isRBFCancelPossible === buttonStatus.possible) { + } else if ( + this.state.isRBFCancelPossible === buttonStatus.possible + ) { return ( - this.props.navigation.navigate('RBFCancel', { + this.props.navigation.navigate("RBFCancel", { txid: this.state.tx.hash, - wallet: this.state.wallet, + wallet: this.state.wallet }) } - style={{ color: '#d0021b', fontSize: 15, fontWeight: '500', textAlign: 'center' }} + style={{ + color: "#d0021b", + fontSize: 15, + fontWeight: "500", + textAlign: "center" + }} > - {'Cancel Transaction'} + {"Cancel Transaction"} @@ -374,11 +450,27 @@ export default class TransactionsStatus extends Component { })()} this.props.navigation.navigate('TransactionDetails', { hash: this.state.tx.hash })} + style={{ + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + marginBottom: 16 + }} + onPress={() => + this.props.navigation.navigate("TransactionDetails", { + hash: this.state.tx.hash + }) + } > - {loc.send.create.details.toLowerCase()} - + + {loc.send.create.details.toLowerCase()} + + @@ -393,8 +485,8 @@ TransactionsStatus.propTypes = { navigate: PropTypes.func, state: PropTypes.shape({ params: PropTypes.shape({ - hash: PropTypes.string, - }), - }), - }), + hash: PropTypes.string + }) + }) + }) }; diff --git a/screen/wallets/add.js b/screen/wallets/add.js index 8f397558f23..acf7884e722 100644 --- a/screen/wallets/add.js +++ b/screen/wallets/add.js @@ -1,7 +1,17 @@ /* global alert */ -import React, { Component } from 'react'; -import { Alert, Text, LayoutAnimation, ActivityIndicator, Keyboard, KeyboardAvoidingView, Platform, View, TextInput } from 'react-native'; -import AsyncStorage from '@react-native-community/async-storage'; +import React, { Component } from "react"; +import { + Alert, + Text, + LayoutAnimation, + ActivityIndicator, + Keyboard, + KeyboardAvoidingView, + Platform, + View, + TextInput +} from "react-native"; +import AsyncStorage from "@react-native-community/async-storage"; import { BlueTextCentered, BlueText, @@ -13,58 +23,66 @@ import { BlueNavigationStyle, BlueButtonLinkUrl, BlueSpacing20, - BlueSpacing10, -} from '../../BlueComponents'; -import { RadioGroup, RadioButton } from 'react-native-flexi-radio-button'; -import PropTypes from 'prop-types'; -import { HDSegwitP2SHWallet } from '../../class/hd-segwit-p2sh-wallet'; -import { HDLegacyP2PKHWallet } from '../../class/hd-legacy-p2pkh-wallet'; -import { AppStorage, HDSegwitBech32Wallet, SegwitP2SHWallet } from '../../class'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -let EV = require('../../events'); -let A = require('../../analytics'); + BlueSpacing10 +} from "../../BlueComponents"; +import { RadioGroup, RadioButton } from "react-native-flexi-radio-button"; +import PropTypes from "prop-types"; +import { HDSegwitP2SHWallet } from "../../class/hd-segwit-p2sh-wallet"; +import { HDLegacyP2PKHWallet } from "../../class/hd-legacy-p2pkh-wallet"; +import { + AppStorage, + HDSegwitBech32Wallet, + SegwitP2SHWallet +} from "../../class"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; + +const EV = require("../../events"); +const A = require("../../analytics"); /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); + export default class WalletsAdd extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), title: loc.wallets.list.add, - headerLeft: null, + headerLeft: null }); constructor(props) { super(props); this.state = { isLoading: true, - walletBaseURI: '', + walletBaseURI: "" }; } async componentDidMount() { let walletBaseURI = await AsyncStorage.getItem(AppStorage.LNDHUB); - let isAdvancedOptionsEnabled = !!(await AsyncStorage.getItem(AppStorage.ADVANCED_MODE_ENABLED)); - walletBaseURI = walletBaseURI || ''; + const isAdvancedOptionsEnabled = !!(await AsyncStorage.getItem( + AppStorage.ADVANCED_MODE_ENABLED + )); + walletBaseURI = walletBaseURI || ""; this.setState({ isLoading: false, activeBitcoin: true, - label: '', + label: "", isAdvancedOptionsEnabled, - walletBaseURI, + walletBaseURI }); } setLabel(text) { this.setState({ - label: text, + label: text }); /* also, a hack to make screen update new typed text */ } onSelect(index, value) { this.setState({ selectedIndex: index, - selectedValue: value, + selectedValue: value }); } @@ -84,12 +102,25 @@ export default class WalletsAdd extends Component { } return ( - - - {loc.wallets.add.wallet_name.slice(0,1).toUpperCase() + loc.wallets.add.wallet_name.slice(1, loc.wallets.add.wallet_name.length)} + + + + {loc.wallets.add.wallet_name.slice(0, 1).toUpperCase() + + loc.wallets.add.wallet_name.slice( + 1, + loc.wallets.add.wallet_name.length + )} + { this.setLabel(text); }} - style={{ flex: 1, marginHorizontal: 8, color: BlueApp.settings.foregroundColor }} + style={{ + flex: 1, + marginHorizontal: 8, + color: BlueApp.settings.foregroundColor + }} editable={!this.state.isLoading} underlineColorAndroid="transparent" /> @@ -117,16 +152,25 @@ export default class WalletsAdd extends Component { {(() => { - if (this.state.activeBitcoin && this.state.isAdvancedOptionsEnabled) { + if ( + this.state.activeBitcoin && + this.state.isAdvancedOptionsEnabled + ) { return ( - {loc.settings.advanced_options} - this.onSelect(index, value)} selectedIndex={0}> + + {loc.settings.advanced_options} + + this.onSelect(index, value)} + selectedIndex={0} + > {HDLegacyP2PKHWallet.typeReadable} @@ -139,15 +183,18 @@ export default class WalletsAdd extends Component { ); - } else if (this.state.activeBitcoin === undefined && this.state.isAdvancedOptionsEnabled) { + } else if ( + this.state.activeBitcoin === undefined && + this.state.isAdvancedOptionsEnabled + ) { return ; } })()} {!this.state.isLoading ? ( @@ -163,16 +210,22 @@ export default class WalletsAdd extends Component { // btc was selected // index 2 radio - hd bip84 w = new HDSegwitBech32Wallet(); - w.setLabel(this.state.label || loc.wallets.details.title); + w.setLabel( + this.state.label || loc.wallets.details.title + ); } else if (this.state.selectedIndex === 1) { // btc was selected // index 1 radio - segwit single address w = new HDSegwitP2SHWallet(); - w.setLabel(this.state.label || loc.wallets.details.title); + w.setLabel( + this.state.label || loc.wallets.details.title + ); } else { // zero index radio - HD segwit w = new HDLegacyP2PKHWallet(); - w.setLabel(this.state.label || loc.wallets.details.title); + w.setLabel( + this.state.label || loc.wallets.details.title + ); } if (this.state.activeBitcoin) { await w.generate(); @@ -180,17 +233,24 @@ export default class WalletsAdd extends Component { await BlueApp.saveToDisk(); EV(EV.enum.WALLETS_COUNT_CHANGED); A(A.ENUM.CREATED_WALLET); - ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false }); - if (w.type === HDSegwitP2SHWallet.type || w.type === HDSegwitBech32Wallet.type || w.type === HDLegacyP2PKHWallet.type) { - this.props.navigation.navigate('PleaseBackup', { - secret: w.getSecret(), + ReactNativeHapticFeedback.trigger( + "notificationSuccess", + { ignoreAndroidSystemSettings: false } + ); + if ( + w.type === HDSegwitP2SHWallet.type || + w.type === HDSegwitBech32Wallet.type || + w.type === HDLegacyP2PKHWallet.type + ) { + this.props.navigation.navigate("PleaseBackup", { + secret: w.getSecret() }); } else { this.props.navigation.dismiss(); } } }, - 1, + 1 ); }} /> @@ -201,7 +261,7 @@ export default class WalletsAdd extends Component { { - this.props.navigation.navigate('ImportWallet'); + this.props.navigation.navigate("ImportWallet"); }} /> @@ -215,6 +275,6 @@ WalletsAdd.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, goBack: PropTypes.func, - dismiss: PropTypes.func, - }), + dismiss: PropTypes.func + }) }; diff --git a/screen/wallets/buyBitcoin.js b/screen/wallets/buyBitcoin.js index 25223d2ed87..62fac171d22 100644 --- a/screen/wallets/buyBitcoin.js +++ b/screen/wallets/buyBitcoin.js @@ -1,39 +1,42 @@ -import React, { Component } from 'react'; -import { BlueNavigationStyle, BlueLoading } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { WebView } from 'react-native-webview'; +import React, { Component } from "react"; +import { BlueNavigationStyle, BlueLoading } from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { WebView } from "react-native-webview"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); export default class BuyBitcoin extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), title: loc.buyBitcoin.header, - headerLeft: null, + headerLeft: null }); constructor(props) { super(props); - let address = props.navigation.state.params.address; - let secret = props.navigation.state.params.secret; + const address = props.navigation.state.params.address; + const secret = props.navigation.state.params.secret; this.state = { isLoading: true, address: address, secret: secret, - addressText: '', + addressText: "" }; } async componentDidMount() { - console.log('buyBitcoin/details - componentDidMount'); + console.log("buyBitcoin/details - componentDidMount"); /** @type {AbstractWallet} */ let wallet; let address = this.state.address; - for (let w of BlueApp.getWallets()) { - if ((address && w.getAddress() === this.state.address) || w.getSecret() === this.state.secret) { + for (const w of BlueApp.getWallets()) { + if ( + (address && w.getAddress() === this.state.address) || + w.getSecret() === this.state.secret + ) { // found our wallet wallet = w; } @@ -46,14 +49,14 @@ export default class BuyBitcoin extends Component { this.setState({ address: address, addressText: address, - isLoading: false, + isLoading: false }); }, 1); } else { this.setState({ isLoading: false, address, - addressText: address, + addressText: address }); } } @@ -65,16 +68,18 @@ export default class BuyBitcoin extends Component { const { safelloStateToken } = this.props.navigation.state.params; - let uri = 'https://bluewallet.io/buy-bitcoin-redirect.html?address=' + this.state.address; + let uri = + "https://bluewallet.io/buy-bitcoin-redirect.html?address=" + + this.state.address; if (safelloStateToken) { - uri += '&safelloStateToken=' + safelloStateToken; + uri += "&safelloStateToken=" + safelloStateToken; } return ( ); @@ -88,8 +93,8 @@ BuyBitcoin.propTypes = { params: PropTypes.shape({ address: PropTypes.string, secret: PropTypes.string, - safelloStateToken: PropTypes.string, - }), - }), - }), + safelloStateToken: PropTypes.string + }) + }) + }) }; diff --git a/screen/wallets/details.js b/screen/wallets/details.js index c80fe129246..29e8bc996ba 100644 --- a/screen/wallets/details.js +++ b/screen/wallets/details.js @@ -1,5 +1,5 @@ /* global alert */ -import React, { Component } from 'react'; +import React, { Component } from "react"; import { ActivityIndicator, View, @@ -10,21 +10,29 @@ import { Keyboard, KeyboardAvoidingView, TouchableWithoutFeedback, - Switch, -} from 'react-native'; -import { BlueButton, SafeBlueArea, BlueCard, BlueSpacing20, BlueNavigationStyle, BlueText } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import { HDLegacyP2PKHWallet } from '../../class/hd-legacy-p2pkh-wallet'; -import { HDSegwitP2SHWallet } from '../../class/hd-segwit-p2sh-wallet'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import Biometric from '../../class/biometrics'; -import { HDSegwitBech32Wallet, WatchOnlyWallet } from '../../class'; -import { ScrollView } from 'react-native-gesture-handler'; -let EV = require('../../events'); -let prompt = require('../../prompt'); + Switch +} from "react-native"; +import { + BlueButton, + SafeBlueArea, + BlueCard, + BlueSpacing20, + BlueNavigationStyle, + BlueText +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import { HDLegacyP2PKHWallet } from "../../class/hd-legacy-p2pkh-wallet"; +import { HDSegwitP2SHWallet } from "../../class/hd-segwit-p2sh-wallet"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import Biometric from "../../class/biometrics"; +import { HDSegwitBech32Wallet, WatchOnlyWallet } from "../../class"; +import { ScrollView } from "react-native-gesture-handler"; + +let EV = require("../../events"); +let prompt = require("../../prompt"); /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); +let BlueApp = require("../../BlueApp"); +let loc = require("../../loc"); export default class WalletDetails extends Component { static navigationOptions = ({ navigation }) => ({ @@ -32,39 +40,49 @@ export default class WalletDetails extends Component { title: loc.wallets.details.title, headerRight: ( { if (navigation.state.params.saveAction) { - navigation.getParam('saveAction')(); + navigation.getParam("saveAction")(); } }} > - {loc.wallets.details.save} + {loc.wallets.details.save} - ), + ) }); constructor(props) { super(props); - const wallet = props.navigation.getParam('wallet'); + const wallet = props.navigation.getParam("wallet"); const isLoading = true; this.state = { isLoading, walletName: wallet.getLabel(), wallet, - useWithHardwareWallet: !!wallet.use_with_hardware_wallet, + useWithHardwareWallet: !!wallet.use_with_hardware_wallet }; - this.props.navigation.setParams({ isLoading, saveAction: () => this.setLabel() }); + this.props.navigation.setParams({ + isLoading, + saveAction: () => this.setLabel() + }); } componentDidMount() { - console.log('wallets/details componentDidMount'); + console.log("wallets/details componentDidMount"); this.setState({ - isLoading: false, + isLoading: false }); - this.props.navigation.setParams({ isLoading: false, saveAction: () => this.setLabel() }); + this.props.navigation.setParams({ + isLoading: false, + saveAction: () => this.setLabel() + }); } setLabel() { @@ -72,33 +90,41 @@ export default class WalletDetails extends Component { this.setState({ isLoading: true }, async () => { this.state.wallet.setLabel(this.state.walletName); BlueApp.saveToDisk(); - alert('Wallet updated.'); + alert("Wallet updated."); this.props.navigation.goBack(null); }); } async presentWalletHasBalanceAlert() { - ReactNativeHapticFeedback.trigger('notificationWarning', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationWarning", { + ignoreAndroidSystemSettings: false + }); const walletBalanceConfirmation = await prompt( - 'Wallet Balance', + "Wallet Balance", `This wallet has a balance. Before proceeding, please be aware that you will not be able to recover the funds without this wallet's seed phrase. In order to avoid accidental removal this wallet, please enter your wallet's balance of ${this.state.wallet.getBalance()} satoshis.`, true, - 'plain-text', + "plain-text" ); if (Number(walletBalanceConfirmation) === this.state.wallet.getBalance()) { this.props.navigation.setParams({ isLoading: true }); this.setState({ isLoading: true }, async () => { BlueApp.deleteWallet(this.state.wallet); - ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationSuccess", { + ignoreAndroidSystemSettings: false + }); await BlueApp.saveToDisk(); EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); EV(EV.enum.WALLETS_COUNT_CHANGED); - this.props.navigation.navigate('Wallets'); + this.props.navigation.navigate("Wallets"); }); } else { - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); this.setState({ isLoading: false }, async () => { - alert("The provided balance amount does not match this wallet's balance. Please, try again"); + alert( + "The provided balance amount does not match this wallet's balance. Please, try again" + ); }); } } @@ -124,23 +150,33 @@ export default class WalletDetails extends Component { - - - - {loc.wallets.add.wallet_name.slice(0,1).toUpperCase() + loc.wallets.add.wallet_name.slice(1, loc.wallets.add.wallet_name.length)} + + + {loc.wallets.add.wallet_name.slice(0, 1).toUpperCase() + + loc.wallets.add.wallet_name.slice( + 1, + loc.wallets.add.wallet_name.length + )} this.setState({ walletName: text })} numberOfLines={1} - style={{ flex: 1, marginHorizontal: 8, minHeight: 33, color: BlueApp.settings.foregroundColor }} + style={{ + flex: 1, + marginHorizontal: 8, + minHeight: 33, + color: BlueApp.settings.foregroundColor + }} editable={!this.state.isLoading} underlineColorAndroid="transparent" /> - + {loc.wallets.details.type} - {this.state.wallet.typeReadable} - + + {this.state.wallet.typeReadable} + + - {this.state.wallet.type === WatchOnlyWallet.type && this.state.wallet.getSecret().startsWith('zpub') && ( - - - {'Use with hardware wallet'} - this.onUseWithHardwareWalletSwitch(value)} /> - - - - )} + {this.state.wallet.type === WatchOnlyWallet.type && + this.state.wallet.getSecret().startsWith("zpub") && ( + + + {"Use with hardware wallet"} + + this.onUseWithHardwareWalletSwitch(value) + } + + + + + )} - this.props.navigation.navigate('WalletExport', { + this.props.navigation.navigate("WalletExport", { address: this.state.wallet.getAddress(), - secret: this.state.wallet.getSecret(), + secret: this.state.wallet.getSecret() }) } title={loc.wallets.details.export_backup} @@ -190,8 +254,8 @@ export default class WalletDetails extends Component { - this.props.navigation.navigate('WalletXpub', { - secret: this.state.wallet.getSecret(), + this.props.navigation.navigate("WalletXpub", { + secret: this.state.wallet.getSecret() }) } title={loc.wallets.details.show_xpub} @@ -203,9 +267,13 @@ export default class WalletDetails extends Component { { - ReactNativeHapticFeedback.trigger('notificationWarning', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationWarning", { + ignoreAndroidSystemSettings: false + }); Alert.alert( - loc.wallets.details.delete + ' ' + loc.wallets.details.title, + loc.wallets.details.delete + + " " + + loc.wallets.details.title, loc.wallets.details.are_you_sure, [ { @@ -221,22 +289,31 @@ export default class WalletDetails extends Component { if (this.state.wallet.getBalance() > 0) { this.presentWalletHasBalanceAlert(); } else { - this.props.navigation.setParams({ isLoading: true }); + this.props.navigation.setParams({ + isLoading: true + }); this.setState({ isLoading: true }, async () => { BlueApp.deleteWallet(this.state.wallet); - ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger( + "notificationSuccess", + { ignoreAndroidSystemSettings: false } + ); await BlueApp.saveToDisk(); EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); EV(EV.enum.WALLETS_COUNT_CHANGED); - this.props.navigation.navigate('Wallets'); + this.props.navigation.navigate("Wallets"); }); } }, - style: 'destructive', + style: "destructive" }, - { text: loc.wallets.details.no_cancel, onPress: () => {}, style: 'cancel' }, + { + text: loc.wallets.details.no_cancel, + onPress: () => {}, + style: "cancel" + } ], - { cancelable: false }, + { cancelable: false } ); }} title={loc.wallets.details.delete} @@ -244,7 +321,6 @@ export default class WalletDetails extends Component { - ); @@ -256,11 +332,11 @@ WalletDetails.propTypes = { getParam: PropTypes.func, state: PropTypes.shape({ params: PropTypes.shape({ - secret: PropTypes.string, - }), + secret: PropTypes.string + }) }), navigate: PropTypes.func, goBack: PropTypes.func, - setParams: PropTypes.func, - }), + setParams: PropTypes.func + }) }; diff --git a/screen/wallets/export.js b/screen/wallets/export.js index e8125e8e216..8e7afb73ac1 100644 --- a/screen/wallets/export.js +++ b/screen/wallets/export.js @@ -1,29 +1,39 @@ -import React, { Component } from 'react'; -import { Dimensions, ActivityIndicator, ScrollView, View, } from 'react-native'; -import QRCode from 'react-native-qrcode-svg'; -import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueCopyTextToClipboard, BlueCard } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import Privacy from '../../Privacy'; -import Biometric from '../../class/biometrics'; +import React, { Component } from "react"; +import { Dimensions, ActivityIndicator, ScrollView, View } from "react-native"; +import QRCode from "react-native-qrcode-svg"; +import { + BlueSpacing20, + SafeBlueArea, + BlueNavigationStyle, + BlueText, + BlueCopyTextToClipboard, + BlueCard +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import Privacy from "../../Privacy"; +import Biometric from "../../class/biometrics"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); -const { height, width } = Dimensions.get('window'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); + +const { height, width } = Dimensions.get("window"); export default class WalletExport extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), - title: loc.wallets.export.title.slice(0,1).toUpperCase() + loc.wallets.export.title.slice(1, loc.wallets.export.title.length), - headerLeft: null, + title: + loc.wallets.export.title.slice(0, 1).toUpperCase() + + loc.wallets.export.title.slice(1, loc.wallets.export.title.length), + headerLeft: null }); constructor(props) { super(props); - let address = props.navigation.state.params.address; - let secret = props.navigation.state.params.secret; + const address = props.navigation.state.params.address; + const secret = props.navigation.state.params.secret; let wallet; - for (let w of BlueApp.getWallets()) { + for (const w of BlueApp.getWallets()) { if ((address && w.getAddress() === address) || w.getSecret() === secret) { // found our wallet wallet = w; @@ -33,7 +43,7 @@ export default class WalletExport extends Component { this.state = { isLoading: true, qrCodeHeight: height > width ? width - 40 : width / 2, - wallet, + wallet }; } @@ -48,7 +58,7 @@ export default class WalletExport extends Component { } this.setState({ - isLoading: false, + isLoading: false }); } @@ -57,7 +67,7 @@ export default class WalletExport extends Component { } onLayout = () => { - const { height } = Dimensions.get('window'); + const { height } = Dimensions.get("window"); this.setState({ qrCodeHeight: height > width ? width - 40 : width / 2 }); }; @@ -74,7 +84,13 @@ export default class WalletExport extends Component { @@ -83,12 +99,12 @@ export default class WalletExport extends Component { @@ -96,10 +112,17 @@ export default class WalletExport extends Component { {loc.wallets.details.mnemoic_seed} - {this.state.wallet.getSecret()} + + {this.state.wallet.getSecret()} + - ); @@ -111,10 +134,10 @@ WalletExport.propTypes = { state: PropTypes.shape({ params: PropTypes.shape({ address: PropTypes.string, - secret: PropTypes.string, - }), + secret: PropTypes.string + }) }), navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/wallets/import.js b/screen/wallets/import.js index 0b794d8002e..3de520143fc 100644 --- a/screen/wallets/import.js +++ b/screen/wallets/import.js @@ -5,10 +5,17 @@ import { WatchOnlyWallet, HDSegwitP2SHWallet, HDLegacyP2PKHWallet, - HDSegwitBech32Wallet, -} from '../../class'; -import React, { Component } from 'react'; -import { KeyboardAvoidingView, Platform, Dimensions, View, TouchableWithoutFeedback, Keyboard } from 'react-native'; + HDSegwitBech32Wallet +} from "../../class"; +import React, { Component } from "react"; +import { + KeyboardAvoidingView, + Platform, + Dimensions, + View, + TouchableWithoutFeedback, + Keyboard +} from "react-native"; import { BlueFormMultiInput, BlueButtonLink, @@ -20,36 +27,40 @@ import { SafeBlueArea, BlueSpacing10, BlueSpacing20, - BlueNavigationStyle, -} from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import Privacy from '../../Privacy'; -let EV = require('../../events'); -let A = require('../../analytics'); + BlueNavigationStyle +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import Privacy from "../../Privacy"; + +const EV = require("../../events"); +const A = require("../../analytics"); /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); -const { width } = Dimensions.get('window'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); + +const { width } = Dimensions.get("window"); export default class WalletsImport extends Component { static navigationOptions = { ...BlueNavigationStyle(), - title: loc.wallets.import.title.slice(0,1).toUpperCase() + loc.wallets.import.title.slice(1, loc.wallets.import.title.length), + title: + loc.wallets.import.title.slice(0, 1).toUpperCase() + + loc.wallets.import.title.slice(1, loc.wallets.import.title.length) }; constructor(props) { super(props); this.state = { isLoading: true, - isToolbarVisibleForAndroid: false, + isToolbarVisibleForAndroid: false }; } componentDidMount() { this.setState({ isLoading: false, - label: '', + label: "" }); Privacy.enableBlur(); } @@ -60,11 +71,13 @@ export default class WalletsImport extends Component { async _saveWallet(w) { if (BlueApp.getWallets().some(wallet => wallet.getSecret() === w.secret)) { - alert('This wallet has been previously imported.'); + alert("This wallet has been previously imported."); } else { alert(loc.wallets.import.success); - ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false }); - w.setLabel(loc.wallets.import.imported + ' ' + w.typeReadable); + ReactNativeHapticFeedback.trigger("notificationSuccess", { + ignoreAndroidSystemSettings: false + }); + w.setLabel(loc.wallets.import.imported + " " + w.typeReadable); BlueApp.wallets.push(w); await BlueApp.saveToDisk(); EV(EV.enum.WALLETS_COUNT_CHANGED); @@ -76,12 +89,12 @@ export default class WalletsImport extends Component { async importMnemonic(text) { try { // trying other wallet types - let segwitWallet = new SegwitP2SHWallet(); + const segwitWallet = new SegwitP2SHWallet(); segwitWallet.setSecret(text); if (segwitWallet.getAddress()) { // ok its a valid WIF - let legacyWallet = new LegacyWallet(); + const legacyWallet = new LegacyWallet(); legacyWallet.setSecret(text); await legacyWallet.fetchBalance(); @@ -99,7 +112,7 @@ export default class WalletsImport extends Component { // case - WIF is valid, just has uncompressed pubkey - let legacyWallet = new LegacyWallet(); + const legacyWallet = new LegacyWallet(); legacyWallet.setSecret(text); if (legacyWallet.getAddress()) { await legacyWallet.fetchBalance(); @@ -109,7 +122,7 @@ export default class WalletsImport extends Component { // if we're here - nope, its not a valid WIF - let hd4 = new HDSegwitBech32Wallet(); + const hd4 = new HDSegwitBech32Wallet(); hd4.setSecret(text); if (hd4.validateMnemonic()) { await hd4.fetchBalance(); @@ -119,7 +132,7 @@ export default class WalletsImport extends Component { } } - let hd2 = new HDSegwitP2SHWallet(); + const hd2 = new HDSegwitP2SHWallet(); hd2.setSecret(text); if (hd2.validateMnemonic()) { await hd2.fetchBalance(); @@ -129,7 +142,7 @@ export default class WalletsImport extends Component { } } - let hd3 = new HDLegacyP2PKHWallet(); + const hd3 = new HDLegacyP2PKHWallet(); hd3.setSecret(text); if (hd3.validateMnemonic()) { await hd3.fetchBalance(); @@ -173,7 +186,7 @@ export default class WalletsImport extends Component { // not valid? maybe its a watch-only address? - let watchOnly = new WatchOnlyWallet(); + const watchOnly = new WatchOnlyWallet(); watchOnly.setSecret(text); if (watchOnly.valid()) { await watchOnly.fetchTransactions(); @@ -189,7 +202,9 @@ export default class WalletsImport extends Component { } alert(loc.wallets.import.error); - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); // Plan: // 0. check if its HDSegwitBech32Wallet (BIP84) // 1. check if its HDSegwitP2SHWallet (BIP49) @@ -204,21 +219,30 @@ export default class WalletsImport extends Component { setLabel(text) { this.setState({ - label: text, + label: text }); /* also, a hack to make screen update new typed text */ } render() { if (this.state.isLoading) { return ( - + ); } return ( - + {loc.wallets.import.explanation} @@ -230,28 +254,42 @@ export default class WalletsImport extends Component { onChangeText={text => { this.setLabel(text); }} - inputAccessoryViewID={BlueDoneAndDismissKeyboardInputAccessory.InputAccessoryViewID} - onFocus={() => this.setState({ isToolbarVisibleForAndroid: true })} - onBlur={() => this.setState({ isToolbarVisibleForAndroid: false })} + inputAccessoryViewID={ + BlueDoneAndDismissKeyboardInputAccessory.InputAccessoryViewID + } + onFocus={() => + this.setState({ isToolbarVisibleForAndroid: true }) + } + onBlur={() => + this.setState({ isToolbarVisibleForAndroid: false }) + } /> {Platform.select({ ios: ( this.setState({ label: '' }, () => Keyboard.dismiss())} - onPasteTapped={text => this.setState({ label: text }, () => Keyboard.dismiss())} + onClearTapped={() => + this.setState({ label: "" }, () => Keyboard.dismiss()) + } + onPasteTapped={text => + this.setState({ label: text }, () => Keyboard.dismiss()) + } /> ), android: this.state.isToolbarVisibleForAndroid && ( this.setState({ label: '' }, () => Keyboard.dismiss())} - onPasteTapped={text => this.setState({ label: text }, () => Keyboard.dismiss())} + onClearTapped={() => + this.setState({ label: "" }, () => Keyboard.dismiss()) + } + onPasteTapped={text => + this.setState({ label: text }, () => Keyboard.dismiss()) + } /> - ), + ) })} @@ -260,14 +298,14 @@ export default class WalletsImport extends Component { { if (!this.state.label) { @@ -283,7 +321,7 @@ export default class WalletsImport extends Component { { - this.props.navigation.navigate('ScanQrWif'); + this.props.navigation.navigate("ScanQrWif"); }} /> @@ -296,6 +334,6 @@ WalletsImport.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, goBack: PropTypes.func, - dismiss: PropTypes.func, - }), + dismiss: PropTypes.func + }) }; diff --git a/screen/wallets/list.js b/screen/wallets/list.js index 972bec94023..df7301261b9 100644 --- a/screen/wallets/list.js +++ b/screen/wallets/list.js @@ -1,38 +1,66 @@ -import React, { Component } from 'react'; -import { View, TouchableOpacity, Text, FlatList, InteractionManager, RefreshControl, ScrollView } from 'react-native'; -import { BlueLoading, SafeBlueArea, WalletsCarousel, BlueList, BlueHeaderDefaultMain, BlueTransactionListItem, NavbarLogo } from '../../BlueComponents'; -import { Icon } from 'react-native-elements'; -import { NavigationEvents } from 'react-navigation'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import PropTypes from 'prop-types'; -let EV = require('../../events'); -let A = require('../../analytics'); +import React, { Component } from "react"; +import { + View, + TouchableOpacity, + Text, + FlatList, + InteractionManager, + RefreshControl, + ScrollView +} from "react-native"; +import { + BlueLoading, + SafeBlueArea, + WalletsCarousel, + BlueList, + BlueHeaderDefaultMain, + BlueTransactionListItem, + NavbarLogo +} from "../../BlueComponents"; +import { Icon } from "react-native-elements"; +import { NavigationEvents } from "react-navigation"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import PropTypes from "prop-types"; + +const EV = require("../../events"); +const A = require("../../analytics"); /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); -let BlueElectrum = require('../../BlueElectrum'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); +const BlueElectrum = require("../../BlueElectrum"); export default class WalletsList extends Component { static navigationOptions = ({ navigation }) => ({ headerStyle: { backgroundColor: BlueApp.settings.navbarColor, borderBottomWidth: 0, - elevation: 0, + elevation: 0 }, headerTitleStyle: { - fontWeight: '600', - color: BlueApp.settings.foregroundColor, + fontWeight: "600", + color: BlueApp.settings.foregroundColor }, headerLeft: , headerRight: ( navigation.navigate('Settings')} + style={{ + marginHorizontal: 16, + width: 40, + height: 40, + justifyContent: "center", + alignItems: "flex-end" + }} + onPress={() => navigation.navigate("Settings")} > - + ), - title: loc.wallets.overview_wallets, + title: loc.wallets.overview_wallets }); constructor(props) { @@ -41,7 +69,7 @@ export default class WalletsList extends Component { isLoading: true, isFlatListRefreshControlHidden: true, wallets: BlueApp.getWallets().concat(false), - lastSnappedTo: 0, + lastSnappedTo: 0 }; EV(EV.enum.WALLETS_COUNT_CHANGED, this.redrawScreen.bind(this)); @@ -58,14 +86,18 @@ export default class WalletsList extends Component { let noErr = true; try { await BlueElectrum.waitTillConnected(); - let balanceStart = +new Date(); + const balanceStart = +new Date(); await BlueApp.fetchWalletBalances(); - let balanceEnd = +new Date(); - console.log('fetch all wallet balances took', (balanceEnd - balanceStart) / 1000, 'sec'); - let start = +new Date(); + const balanceEnd = +new Date(); + console.log( + "fetch all wallet balances took", + (balanceEnd - balanceStart) / 1000, + "sec" + ); + const start = +new Date(); await BlueApp.fetchWalletTransactions(); - let end = +new Date(); - console.log('fetch all wallet txs took', (end - start) / 1000, 'sec'); + const end = +new Date(); + console.log("fetch all wallet txs took", (end - start) / 1000, "sec"); } catch (_) { noErr = false; } @@ -78,14 +110,17 @@ export default class WalletsList extends Component { * Triggered manually by user on pull-to-refresh. */ refreshTransactions() { - if (!(this.lastSnappedTo < BlueApp.getWallets().length) && this.lastSnappedTo !== undefined) { + if ( + !(this.lastSnappedTo < BlueApp.getWallets().length) && + this.lastSnappedTo !== undefined + ) { // last card, nop - console.log('last card, nop'); + console.log("last card, nop"); return; } this.setState( { - isFlatListRefreshControlHidden: false, + isFlatListRefreshControlHidden: false }, () => { InteractionManager.runAfterInteractions(async () => { @@ -93,14 +128,18 @@ export default class WalletsList extends Component { try { await BlueElectrum.ping(); await BlueElectrum.waitTillConnected(); - let balanceStart = +new Date(); + const balanceStart = +new Date(); await BlueApp.fetchWalletBalances(this.lastSnappedTo || 0); - let balanceEnd = +new Date(); - console.log('fetch balance took', (balanceEnd - balanceStart) / 1000, 'sec'); - let start = +new Date(); + const balanceEnd = +new Date(); + console.log( + "fetch balance took", + (balanceEnd - balanceStart) / 1000, + "sec" + ); + const start = +new Date(); await BlueApp.fetchWalletTransactions(this.lastSnappedTo || 0); - let end = +new Date(); - console.log('fetch tx took', (end - start) / 1000, 'sec'); + const end = +new Date(); + console.log("fetch tx took", (end - start) / 1000, "sec"); } catch (err) { noErr = false; console.warn(err); @@ -109,12 +148,12 @@ export default class WalletsList extends Component { this.redrawScreen(); }); - }, + } ); } redrawScreen() { - console.log('wallets/list redrawScreen()'); + console.log("wallets/list redrawScreen()"); if (BlueApp.getBalance() !== 0) { A(A.ENUM.GOT_NONZERO_BALANCE); } else { @@ -125,33 +164,33 @@ export default class WalletsList extends Component { isLoading: false, isFlatListRefreshControlHidden: true, dataSource: BlueApp.getTransactions(null, 10), - wallets: BlueApp.getWallets().concat(false), + wallets: BlueApp.getWallets().concat(false) }); } txMemo(hash) { - if (BlueApp.tx_metadata[hash] && BlueApp.tx_metadata[hash]['memo']) { - return BlueApp.tx_metadata[hash]['memo']; + if (BlueApp.tx_metadata[hash] && BlueApp.tx_metadata[hash]["memo"]) { + return BlueApp.tx_metadata[hash]["memo"]; } - return ''; + return ""; } handleClick(index) { - console.log('click', index); - let wallet = BlueApp.wallets[index]; + console.log("click", index); + const wallet = BlueApp.wallets[index]; if (wallet) { - this.props.navigation.navigate('WalletTransactions', { + this.props.navigation.navigate("WalletTransactions", { wallet: wallet, - key: `WalletTransactions-${wallet.getID()}`, + key: `WalletTransactions-${wallet.getID()}` }); } else { // if its out of index - this must be last card with incentive to create wallet - this.props.navigation.navigate('AddWallet'); + this.props.navigation.navigate("AddWallet"); } } onSnapToItem(index) { - console.log('onSnapToItem', index); + console.log("onSnapToItem", index); this.lastSnappedTo = index; this.setState({ lastSnappedTo: index }); @@ -171,27 +210,33 @@ export default class WalletsList extends Component { */ async lazyRefreshWallet(index) { /** @type {Array.} wallets */ - let wallets = BlueApp.getWallets(); + const wallets = BlueApp.getWallets(); if (!wallets[index]) { return; } - let oldBalance = wallets[index].getBalance(); + const oldBalance = wallets[index].getBalance(); let noErr = true; let didRefresh = false; try { if (wallets && wallets[index] && wallets[index].timeToRefreshBalance()) { - console.log('snapped to, and now its time to refresh wallet #', index); + console.log("snapped to, and now its time to refresh wallet #", index); await wallets[index].fetchBalance(); - if (oldBalance !== wallets[index].getBalance() || wallets[index].getUnconfirmedBalance() !== 0) { - console.log('balance changed, thus txs too'); + if ( + oldBalance !== wallets[index].getBalance() || + wallets[index].getUnconfirmedBalance() !== 0 + ) { + console.log("balance changed, thus txs too"); // balance changed, thus txs too await wallets[index].fetchTransactions(); this.redrawScreen(); didRefresh = true; } else if (wallets[index].timeToRefreshTransaction()) { - console.log(wallets[index].getLabel(), 'thinks its time to refresh TXs'); + console.log( + wallets[index].getLabel(), + "thinks its time to refresh TXs" + ); await wallets[index].fetchTransactions(); if (wallets[index].fetchPendingTransactions) { await wallets[index].fetchPendingTransactions(); @@ -203,7 +248,7 @@ export default class WalletsList extends Component { this.redrawScreen(); didRefresh = true; } else { - console.log('balance not changed'); + console.log("balance not changed"); } } } catch (Err) { @@ -224,10 +269,10 @@ export default class WalletsList extends Component { {loc.transactions.list.tabBarLabel} @@ -238,25 +283,32 @@ export default class WalletsList extends Component { handleLongPress = () => { if (BlueApp.getWallets().length > 1) { - this.props.navigation.navigate('ReorderWallets'); + this.props.navigation.navigate("ReorderWallets"); } else { - ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("notificationError", { + ignoreAndroidSystemSettings: false + }); } }; /* Outcomented but maybe will be used in future * this.props.navigation.navigate('AddWallet')} /> - */ + */ _renderItem = data => { - return ; + return ( + + ); }; render() { if (this.state.isLoading) { return ; } return ( - + { this.redrawScreen(); @@ -264,7 +316,10 @@ export default class WalletsList extends Component { /> this.refreshTransactions()} refreshing={!this.state.isFlatListRefreshControlHidden} /> + this.refreshTransactions()} + refreshing={!this.state.isFlatListRefreshControlHidden} + /> } > {loc.wallets.list.empty_txs1} @@ -295,8 +350,8 @@ export default class WalletsList extends Component { {loc.wallets.list.empty_txs2} @@ -317,6 +372,6 @@ export default class WalletsList extends Component { WalletsList.propTypes = { navigation: PropTypes.shape({ - navigate: PropTypes.func, - }), + navigate: PropTypes.func + }) }; diff --git a/screen/wallets/marketplace.js b/screen/wallets/marketplace.js index 907c9be3453..ec6e1e764ab 100644 --- a/screen/wallets/marketplace.js +++ b/screen/wallets/marketplace.js @@ -1,27 +1,31 @@ -import React, { Component } from 'react'; -import { BackHandler } from 'react-native'; -import { WebView } from 'react-native-webview'; -import { BlueLoading, BlueNavigationStyle } from '../../BlueComponents'; -import PropTypes from 'prop-types'; +import React, { Component } from "react"; +import { BackHandler } from "react-native"; +import { WebView } from "react-native-webview"; +import { BlueLoading, BlueNavigationStyle } from "../../BlueComponents"; +import PropTypes from "prop-types"; export default class Marketplace extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), - title: 'Marketplace', - headerLeft: null, + title: "Marketplace", + headerLeft: null }); constructor(props) { super(props); - if (!props.navigation.getParam('fromWallet')) throw new Error('Invalid param'); - let fromWallet = props.navigation.getParam('fromWallet'); + if (!props.navigation.getParam("fromWallet")) + throw new Error("Invalid param"); + const fromWallet = props.navigation.getParam("fromWallet"); this.state = { - url: '', + url: "", fromWallet, - canGoBack: false, + canGoBack: false }; - BackHandler.addEventListener('hardwareBackPress', this.handleBackButton.bind(this)); + BackHandler.addEventListener( + "hardwareBackPress", + this.handleBackButton.bind(this) + ); } async componentDidMount() { @@ -32,19 +36,24 @@ export default class Marketplace extends Component { address = this.state.fromWallet.getAddress(); } - let url = 'https://bluewallet.io/marketplace-btc/?address=' + address; // default + const url = "https://bluewallet.io/marketplace-btc/?address=" + address; // default this.setState({ - url, + url }); } componentWillUnmount = () => { - BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton.bind(this)); + BackHandler.removeEventListener( + "hardwareBackPress", + this.handleBackButton.bind(this) + ); }; handleBackButton() { - this.state.canGoBack ? this.webview.goBack() : this.props.navigation.goBack(null); + this.state.canGoBack + ? this.webview.goBack() + : this.props.navigation.goBack(null); return true; } @@ -62,7 +71,7 @@ export default class Marketplace extends Component { ref={ref => (this.webview = ref)} onNavigationStateChange={this._onNavigationStateChange} source={{ - uri: this.state.url, + uri: this.state.url }} /> ); @@ -73,6 +82,6 @@ Marketplace.propTypes = { navigation: PropTypes.shape({ getParam: PropTypes.func, navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/screen/wallets/pleaseBackup.js b/screen/wallets/pleaseBackup.js index b508c24e533..c2b25966021 100644 --- a/screen/wallets/pleaseBackup.js +++ b/screen/wallets/pleaseBackup.js @@ -1,19 +1,26 @@ -import React, { Component } from 'react'; -import { ActivityIndicator, View, BackHandler, Text } from 'react-native'; -import { BlueSpacing20, SafeBlueArea, BlueNavigationStyle, BlueText, BlueButton } from '../../BlueComponents'; -import { Badge } from 'react-native-elements'; -import PropTypes from 'prop-types'; -import Privacy from '../../Privacy'; -import { ScrollView } from 'react-native-gesture-handler'; -let loc = require('../../loc'); -let BlueApp = require('../../BlueApp'); +import React, { Component } from "react"; +import { ActivityIndicator, View, BackHandler, Text } from "react-native"; +import { + BlueSpacing20, + SafeBlueArea, + BlueNavigationStyle, + BlueText, + BlueButton +} from "../../BlueComponents"; +import { Badge } from "react-native-elements"; +import PropTypes from "prop-types"; +import Privacy from "../../Privacy"; +import { ScrollView } from "react-native-gesture-handler"; + +const loc = require("../../loc"); +const BlueApp = require("../../BlueApp"); export default class PleaseBackup extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), title: loc.pleasebackup.title, headerLeft: null, - headerRight: null, + headerRight: null }); constructor(props) { @@ -21,9 +28,12 @@ export default class PleaseBackup extends Component { this.state = { isLoading: true, - words: props.navigation.state.params.secret.split(' '), + words: props.navigation.state.params.secret.split(" ") }; - BackHandler.addEventListener('hardwareBackPress', this.handleBackButton.bind(this)); + BackHandler.addEventListener( + "hardwareBackPress", + this.handleBackButton.bind(this) + ); } handleBackButton() { @@ -34,13 +44,16 @@ export default class PleaseBackup extends Component { componentDidMount() { Privacy.enableBlur(); this.setState({ - isLoading: false, + isLoading: false }); } componentWillUnmount() { Privacy.disableBlur(); - BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton.bind(this)); + BackHandler.removeEventListener( + "hardwareBackPress", + this.handleBackButton.bind(this) + ); } render() { @@ -54,21 +67,38 @@ export default class PleaseBackup extends Component { return ( - - - {loc.pleasebackup.success} - {loc.pleasebackup.text} + + + + {loc.pleasebackup.success} + + + {loc.pleasebackup.text} + - + - 1. {this.state.words[0]} + + 1. {this.state.words[0]} + - + - 2. {this.state.words[1]} + + 2. {this.state.words[1]} + - + - 3. {this.state.words[2]} + + 3. {this.state.words[2]} + - + - 4. {this.state.words[3]} + + 4. {this.state.words[3]} + - + - 5. {this.state.words[4]} + + 5. {this.state.words[4]} + - + - 6. {this.state.words[5]} + + 6. {this.state.words[5]} + - + - 7. {this.state.words[6]} + + 7. {this.state.words[6]} + - + - 8. {this.state.words[7]} + + 8. {this.state.words[7]} + - + - 9. {this.state.words[8]} + + 9. {this.state.words[8]} + - + - 10. {this.state.words[9]} + + 10. {this.state.words[9]} + - + - 11. {this.state.words[10]} + + 11. {this.state.words[10]} + - + - 12. {this.state.words[11]} + + 12. {this.state.words[11]} + - + - 13. {this.state.words[12]} + + 13. {this.state.words[12]} + - + - 14. {this.state.words[13]} + + 14. {this.state.words[13]} + - + - 15. {this.state.words[14]} + + 15. {this.state.words[14]} + - + - 16. {this.state.words[15]} + + 16. {this.state.words[15]} + - + - 17. {this.state.words[16]} + + 17. {this.state.words[16]} + - + - 18. {this.state.words[17]} + + 18. {this.state.words[17]} + - + - 19. {this.state.words[18]} + + 19. {this.state.words[18]} + - + - 20. {this.state.words[19]} + + 20. {this.state.words[19]} + - + - 21. {this.state.words[20]} + + 21. {this.state.words[20]} + - + - 22. {this.state.words[21]} + + 22. {this.state.words[21]} + - + - 23. {this.state.words[22]} + + 23. {this.state.words[22]} + - + - 24. {this.state.words[23]} + + 24. {this.state.words[23]} + - + - this.props.navigation.dismiss()} title={loc.pleasebackup.ok} /> + this.props.navigation.dismiss()} + title={loc.pleasebackup.ok} + /> @@ -423,9 +513,9 @@ PleaseBackup.propTypes = { navigation: PropTypes.shape({ state: PropTypes.shape({ params: PropTypes.shape({ - secret: PropTypes.string, - }), + secret: PropTypes.string + }) }), - dismiss: PropTypes.func, - }), + dismiss: PropTypes.func + }) }; diff --git a/screen/wallets/reorderWallets.js b/screen/wallets/reorderWallets.js index d864804e88b..e0e69002f8e 100644 --- a/screen/wallets/reorderWallets.js +++ b/screen/wallets/reorderWallets.js @@ -1,24 +1,27 @@ -import React, { Component } from 'react'; -import { View, ActivityIndicator, Image, Text } from 'react-native'; -import { SafeBlueArea, BlueNavigationStyle } from '../../BlueComponents'; -import SortableList from 'react-native-sortable-list'; -import LinearGradient from 'react-native-linear-gradient'; -import PropTypes from 'prop-types'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import WalletGradient from '../../class/walletGradient'; -let EV = require('../../events'); +import React, { Component } from "react"; +import { View, ActivityIndicator, Image, Text } from "react-native"; +import { SafeBlueArea, BlueNavigationStyle } from "../../BlueComponents"; +import SortableList from "react-native-sortable-list"; +import LinearGradient from "react-native-linear-gradient"; +import PropTypes from "prop-types"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import WalletGradient from "../../class/walletGradient"; + +const EV = require("../../events"); /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc/'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc/"); export default class ReorderWallets extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle( navigation, true, - navigation.getParam('customCloseButtonFunction') ? navigation.state.params.customCloseButtonFunction : undefined, + navigation.getParam("customCloseButtonFunction") + ? navigation.state.params.customCloseButtonFunction + : undefined ), - title: loc.wallets.reorder.title, + title: loc.wallets.reorder.title }); constructor(props) { @@ -26,15 +29,18 @@ export default class ReorderWallets extends Component { this.state = { isLoading: true, data: [], - hasMovedARow: false, + hasMovedARow: false }; } componentDidMount() { this.props.navigation.setParams({ customCloseButtonFunction: async () => { - if (this.sortableList.state.data.length === this.state.data.length && this.state.hasMovedARow) { - let newWalletsOrderArray = []; + if ( + this.sortableList.state.data.length === this.state.data.length && + this.state.hasMovedARow + ) { + const newWalletsOrderArray = []; this.sortableList.state.order.forEach(element => { newWalletsOrderArray.push(this.state.data[element]); }); @@ -47,13 +53,13 @@ export default class ReorderWallets extends Component { } else { this.props.navigation.dismiss(); } - }, + } }); const wallets = BlueApp.getWallets(); this.setState({ data: wallets, - isLoading: false, + isLoading: false }); } @@ -68,7 +74,11 @@ export default class ReorderWallets extends Component { shadowOpacity={40 / 100} shadowOffset={{ width: 0, height: 0 }} shadowRadius={5} - style={{ backgroundColor: 'transparent', padding: 10, marginVertical: 17 }} + style={{ + backgroundColor: "transparent", + padding: 10, + marginVertical: 17 + }} > - + {item.getLabel()} @@ -108,21 +116,25 @@ export default class ReorderWallets extends Component { numberOfLines={1} adjustsFontSizeToFit style={{ - backgroundColor: 'transparent', - fontWeight: 'bold', + backgroundColor: "transparent", + fontWeight: "bold", fontSize: 36, - color: '#fff', + color: "#fff" }} > - {loc.formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)} + {loc.formatBalance( + Number(item.getBalance()), + item.getPreferredBalanceUnit(), + true + )} - + {loc.wallets.list.latest_transaction} @@ -130,10 +142,10 @@ export default class ReorderWallets extends Component { {loc.transactionTimeToReadable(item.getLatestTransactionTime())} @@ -160,14 +172,20 @@ export default class ReorderWallets extends Component { data={this.state.data} renderRow={this._renderItem} onChangeOrder={() => { - ReactNativeHapticFeedback.trigger('impactMedium', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("impactMedium", { + ignoreAndroidSystemSettings: false + }); this.setState({ hasMovedARow: true }); }} onActivateRow={() => { - ReactNativeHapticFeedback.trigger('selection', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("selection", { + ignoreAndroidSystemSettings: false + }); }} onReleaseRow={() => { - ReactNativeHapticFeedback.trigger('impactLight', { ignoreAndroidSystemSettings: false }); + ReactNativeHapticFeedback.trigger("impactLight", { + ignoreAndroidSystemSettings: false + }); }} /> @@ -179,6 +197,6 @@ ReorderWallets.propTypes = { navigation: PropTypes.shape({ navigate: PropTypes.func, setParams: PropTypes.func, - dismiss: PropTypes.func, - }), + dismiss: PropTypes.func + }) }; diff --git a/screen/wallets/scanQrWif.js b/screen/wallets/scanQrWif.js index e33e0a10243..96dba342c4e 100644 --- a/screen/wallets/scanQrWif.js +++ b/screen/wallets/scanQrWif.js @@ -1,58 +1,84 @@ /* global alert */ -import React from 'react'; -import { ActivityIndicator, Image, View, TouchableOpacity } from 'react-native'; -import { BlueText, SafeBlueArea, BlueButton } from '../../BlueComponents'; -import { RNCamera } from 'react-native-camera'; -import { SegwitP2SHWallet, LegacyWallet, WatchOnlyWallet, HDLegacyP2PKHWallet, HDSegwitBech32Wallet } from '../../class'; -import PropTypes from 'prop-types'; -import { HDSegwitP2SHWallet } from '../../class/hd-segwit-p2sh-wallet'; -import bip21 from 'bip21'; +import React from "react"; +import { ActivityIndicator, Image, View, TouchableOpacity } from "react-native"; +import { BlueText, SafeBlueArea, BlueButton } from "../../BlueComponents"; +import { RNCamera } from "react-native-camera"; +import { + SegwitP2SHWallet, + LegacyWallet, + WatchOnlyWallet, + HDLegacyP2PKHWallet, + HDSegwitBech32Wallet +} from "../../class"; +import PropTypes from "prop-types"; +import { HDSegwitP2SHWallet } from "../../class/hd-segwit-p2sh-wallet"; +import bip21 from "bip21"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let EV = require('../../events'); -let bip38 = require('../../bip38'); -let wif = require('wif'); -let prompt = require('../../prompt'); -let loc = require('../../loc'); +const BlueApp = require("../../BlueApp"); +const EV = require("../../events"); +const bip38 = require("../../bip38"); +const wif = require("wif"); +const prompt = require("../../prompt"); +const loc = require("../../loc"); export default class ScanQrWif extends React.Component { static navigationOptions = { - header: null, + header: null }; state = { isLoading: false }; onBarCodeScanned = async ret => { - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.pausePreview(); + if ( + RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.pausePreview(); if (+new Date() - this.lastTimeIveBeenHere < 6000) { this.lastTimeIveBeenHere = +new Date(); return; } this.lastTimeIveBeenHere = +new Date(); this.setState({ isLoading: true }); - if (ret.data[0] === '6') { + if (ret.data[0] === "6") { // password-encrypted, need to ask for password and decrypt - console.log('trying to decrypt...'); + console.log("trying to decrypt..."); this.setState({ - message: loc.wallets.scanQrWif.decoding, + message: loc.wallets.scanQrWif.decoding }); shold_stop_bip38 = undefined; // eslint-disable-line - let password = await prompt(loc.wallets.scanQrWif.input_password, loc.wallets.scanQrWif.password_explain); + const password = await prompt( + loc.wallets.scanQrWif.input_password, + loc.wallets.scanQrWif.password_explain + ); if (!password) { return; } - let that = this; + const that = this; try { - let decryptedKey = await bip38.decrypt(ret.data, password, function(status) { + const decryptedKey = await bip38.decrypt(ret.data, password, function( + status + ) { that.setState({ - message: loc.wallets.scanQrWif.decoding + '... ' + status.percent.toString().substr(0, 4) + ' %', + message: + loc.wallets.scanQrWif.decoding + + "... " + + status.percent.toString().substr(0, 4) + + " %" }); }); - ret.data = wif.encode(0x80, decryptedKey.privateKey, decryptedKey.compressed); + ret.data = wif.encode( + 0x80, + decryptedKey.privateKey, + decryptedKey.compressed + ); } catch (e) { console.log(e.message); - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.resumePreview(); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.resumePreview(); this.setState({ message: false, isLoading: false }); return alert(loc.wallets.scanQrWif.bad_password); } @@ -60,21 +86,28 @@ export default class ScanQrWif extends React.Component { this.setState({ message: false, isLoading: false }); } - for (let w of BlueApp.wallets) { + for (const w of BlueApp.wallets) { if (w.getSecret() === ret.data) { // lookig for duplicates this.setState({ isLoading: false }); - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.resumePreview(); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.resumePreview(); return alert(loc.wallets.scanQrWif.wallet_already_exists); // duplicate, not adding } } // is it just address..? - let watchOnly = new WatchOnlyWallet(); + const watchOnly = new WatchOnlyWallet(); let watchAddr = ret.data; // Is it BIP21 format? - if (ret.data.indexOf('bitcoin:') === 0 || ret.data.indexOf('BITCOIN:') === 0) { + if ( + ret.data.indexOf("bitcoin:") === 0 || + ret.data.indexOf("BITCOIN:") === 0 + ) { try { watchAddr = bip21.decode(ret.data).address; } catch (err) { @@ -84,9 +117,11 @@ export default class ScanQrWif extends React.Component { // Or is it a bare address? // TODO: remove these hardcodes - if (ret.data.indexOf('V') === 0 - || ret.data.indexOf('D') === 0 - || ret.data.indexOf('veles') === 0 ) { + if ( + ret.data.indexOf("V") === 0 || + ret.data.indexOf("D") === 0 || + ret.data.indexOf("veles") === 0 + ) { try { watchAddr = ret.data; } catch (err) { @@ -97,7 +132,11 @@ export default class ScanQrWif extends React.Component { if (watchOnly.setSecret(watchAddr) && watchOnly.valid()) { watchOnly.setLabel(loc.wallets.scanQrWif.imported_watchonly); BlueApp.wallets.push(watchOnly); - alert(loc.wallets.scanQrWif.imported_watchonly + loc.wallets.scanQrWif.with_address + watchOnly.getAddress()); + alert( + loc.wallets.scanQrWif.imported_watchonly + + loc.wallets.scanQrWif.with_address + + watchOnly.getAddress() + ); await watchOnly.fetchBalance(); await watchOnly.fetchTransactions(); await BlueApp.saveToDisk(); @@ -112,16 +151,20 @@ export default class ScanQrWif extends React.Component { let hd = new HDSegwitBech32Wallet(); hd.setSecret(ret.data); if (hd.validateMnemonic()) { - for (let w of BlueApp.wallets) { + for (const w of BlueApp.wallets) { if (w.getSecret() === hd.getSecret()) { // lookig for duplicates this.setState({ isLoading: false }); - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.resumePreview(); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.resumePreview(); return alert(loc.wallets.scanQrWif.wallet_already_exists); // duplicate, not adding } } this.setState({ isLoading: true }); - hd.setLabel(loc.wallets.import.imported + ' ' + hd.typeReadable); + hd.setLabel(loc.wallets.import.imported + " " + hd.typeReadable); await hd.fetchBalance(); if (hd.getBalance() !== 0) { await hd.fetchTransactions(); @@ -140,18 +183,22 @@ export default class ScanQrWif extends React.Component { hd = new HDLegacyP2PKHWallet(); hd.setSecret(ret.data); if (hd.validateMnemonic()) { - for (let w of BlueApp.wallets) { + for (const w of BlueApp.wallets) { if (w.getSecret() === hd.getSecret()) { // lookig for duplicates this.setState({ isLoading: false }); - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.resumePreview(); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.resumePreview(); return alert(loc.wallets.scanQrWif.wallet_already_exists); // duplicate, not adding } } await hd.fetchTransactions(); if (hd.getTransactions().length !== 0) { await hd.fetchBalance(); - hd.setLabel(loc.wallets.import.imported + ' ' + hd.typeReadable); + hd.setLabel(loc.wallets.import.imported + " " + hd.typeReadable); BlueApp.wallets.push(hd); await BlueApp.saveToDisk(); alert(loc.wallets.import.success); @@ -167,16 +214,20 @@ export default class ScanQrWif extends React.Component { hd = new HDSegwitP2SHWallet(); hd.setSecret(ret.data); if (hd.validateMnemonic()) { - for (let w of BlueApp.wallets) { + for (const w of BlueApp.wallets) { if (w.getSecret() === hd.getSecret()) { // lookig for duplicates this.setState({ isLoading: false }); - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.resumePreview(); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.resumePreview(); return alert(loc.wallets.scanQrWif.wallet_already_exists); // duplicate, not adding } } this.setState({ isLoading: true }); - hd.setLabel(loc.wallets.import.imported + ' ' + hd.typeReadable); + hd.setLabel(loc.wallets.import.imported + " " + hd.typeReadable); BlueApp.wallets.push(hd); await hd.fetchBalance(); await hd.fetchTransactions(); @@ -189,23 +240,38 @@ export default class ScanQrWif extends React.Component { } // nope - let newWallet = new SegwitP2SHWallet(); + const newWallet = new SegwitP2SHWallet(); newWallet.setSecret(ret.data); - let newLegacyWallet = new LegacyWallet(); + const newLegacyWallet = new LegacyWallet(); newLegacyWallet.setSecret(ret.data); - if (newWallet.getAddress() === false && newLegacyWallet.getAddress() === false) { + if ( + newWallet.getAddress() === false && + newLegacyWallet.getAddress() === false + ) { alert(loc.wallets.scanQrWif.bad_wif); - if (RNCamera.Constants.CameraStatus === RNCamera.Constants.CameraStatus.READY) this.cameraRef.resumePreview(); + if ( + RNCamera.Constants.CameraStatus === + RNCamera.Constants.CameraStatus.READY + ) + this.cameraRef.resumePreview(); this.setState({ isLoading: false }); return; } - if (newWallet.getAddress() === false && newLegacyWallet.getAddress() !== false) { + if ( + newWallet.getAddress() === false && + newLegacyWallet.getAddress() !== false + ) { // case - WIF is valid, just has uncompressed pubkey newLegacyWallet.setLabel(loc.wallets.scanQrWif.imported_legacy); BlueApp.wallets.push(newLegacyWallet); - alert(loc.wallets.scanQrWif.imported_wif + ret.data + loc.wallets.scanQrWif.with_address + newLegacyWallet.getAddress()); + alert( + loc.wallets.scanQrWif.imported_wif + + ret.data + + loc.wallets.scanQrWif.with_address + + newLegacyWallet.getAddress() + ); await newLegacyWallet.fetchBalance(); await newLegacyWallet.fetchTransactions(); await BlueApp.saveToDisk(); @@ -216,19 +282,29 @@ export default class ScanQrWif extends React.Component { this.setState({ isLoading: true }); await newLegacyWallet.fetchBalance(); - console.log('newLegacyWallet == ', newLegacyWallet.getBalance()); + console.log("newLegacyWallet == ", newLegacyWallet.getBalance()); if (newLegacyWallet.getBalance()) { newLegacyWallet.setLabel(loc.wallets.scanQrWif.imported_legacy); BlueApp.wallets.push(newLegacyWallet); - alert(loc.wallets.scanQrWif.imported_wif + ret.data + loc.wallets.scanQrWif.with_address + newLegacyWallet.getAddress()); + alert( + loc.wallets.scanQrWif.imported_wif + + ret.data + + loc.wallets.scanQrWif.with_address + + newLegacyWallet.getAddress() + ); await newLegacyWallet.fetchTransactions(); } else { await newWallet.fetchBalance(); await newWallet.fetchTransactions(); newWallet.setLabel(loc.wallets.scanQrWif.imported_segwit); BlueApp.wallets.push(newWallet); - alert(loc.wallets.scanQrWif.imported_wif + ret.data + loc.wallets.scanQrWif.with_address + newWallet.getAddress()); + alert( + loc.wallets.scanQrWif.imported_wif + + ret.data + + loc.wallets.scanQrWif.with_address + + newWallet.getAddress() + ); } await BlueApp.saveToDisk(); this.props.navigation.popToTop(); @@ -238,7 +314,14 @@ export default class ScanQrWif extends React.Component { render() { if (this.state.isLoading) { return ( - + ); @@ -252,14 +335,14 @@ export default class ScanQrWif extends React.Component { {this.state.message} { this.setState({ message: false }); shold_stop_bip38 = true; // eslint-disable-line @@ -275,12 +358,12 @@ export default class ScanQrWif extends React.Component { (this.cameraRef = ref)} barCodeTypes={[RNCamera.Constants.BarCodeType.qr]} @@ -291,14 +374,17 @@ export default class ScanQrWif extends React.Component { height: 40, marginLeft: 24, backgroundColor: BlueApp.settings.brandingColor, - justifyContent: 'center', + justifyContent: "center", borderRadius: 20, - position: 'absolute', - top: 64, + position: "absolute", + top: 64 }} onPress={() => this.props.navigation.goBack(null)} > - + ); @@ -313,6 +399,6 @@ ScanQrWif.propTypes = { navigation: PropTypes.shape({ goBack: PropTypes.func, popToTop: PropTypes.func, - navigate: PropTypes.func, - }), + navigate: PropTypes.func + }) }; diff --git a/screen/wallets/selectWallet.js b/screen/wallets/selectWallet.js index 196819a0c1a..3a4b71809f5 100644 --- a/screen/wallets/selectWallet.js +++ b/screen/wallets/selectWallet.js @@ -1,18 +1,35 @@ -import React, { Component } from 'react'; -import { View, ActivityIndicator, Image, Text, TouchableOpacity, FlatList } from 'react-native'; -import { SafeBlueArea, BlueNavigationStyle, BlueText, BlueSpacing20, BluePrivateBalance } from '../../BlueComponents'; -import LinearGradient from 'react-native-linear-gradient'; -import PropTypes from 'prop-types'; -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import WalletGradient from '../../class/walletGradient'; +import React, { Component } from "react"; +import { + View, + ActivityIndicator, + Image, + Text, + TouchableOpacity, + FlatList +} from "react-native"; +import { + SafeBlueArea, + BlueNavigationStyle, + BlueText, + BlueSpacing20, + BluePrivateBalance +} from "../../BlueComponents"; +import LinearGradient from "react-native-linear-gradient"; +import PropTypes from "prop-types"; +import ReactNativeHapticFeedback from "react-native-haptic-feedback"; +import WalletGradient from "../../class/walletGradient"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); export default class SelectWallet extends Component { static navigationOptions = ({ navigation }) => ({ - ...BlueNavigationStyle(navigation, true, navigation.getParam('dismissAcion')), - title: loc.wallets.select_wallet, + ...BlueNavigationStyle( + navigation, + true, + navigation.getParam("dismissAcion") + ), + title: loc.wallets.select_wallet }); constructor(props) { @@ -20,9 +37,9 @@ export default class SelectWallet extends Component { props.navigation.setParams({ dismissAcion: this.dismissComponent }); this.state = { isLoading: true, - data: [], + data: [] }; - this.chainType = props.navigation.getParam('chainType'); + this.chainType = props.navigation.getParam("chainType"); } dismissComponent = () => { @@ -31,11 +48,13 @@ export default class SelectWallet extends Component { componentDidMount() { const wallets = this.chainType - ? BlueApp.getWallets().filter(item => item.chain === this.chainType && item.allowSend()) + ? BlueApp.getWallets().filter( + item => item.chain === this.chainType && item.allowSend() + ) : BlueApp.getWallets(); this.setState({ data: wallets, - isLoading: false, + isLoading: false }); } @@ -43,15 +62,21 @@ export default class SelectWallet extends Component { return ( { - ReactNativeHapticFeedback.trigger('selection', { ignoreAndroidSystemSettings: false }); - this.props.navigation.getParam('onWalletSelect')(item); + ReactNativeHapticFeedback.trigger("selection", { + ignoreAndroidSystemSettings: false + }); + this.props.navigation.getParam("onWalletSelect")(item); }} > - + {item.getLabel()} @@ -94,22 +117,26 @@ export default class SelectWallet extends Component { numberOfLines={1} adjustsFontSizeToFit style={{ - backgroundColor: 'transparent', - fontWeight: 'bold', + backgroundColor: "transparent", + fontWeight: "bold", fontSize: 36, - color: '#fff', + color: "#fff" }} > - {loc.formatBalance(Number(item.getBalance()), item.getPreferredBalanceUnit(), true)} + {loc.formatBalance( + Number(item.getBalance()), + item.getPreferredBalanceUnit(), + true + )} )} - + {loc.wallets.list.latest_transaction} @@ -117,10 +144,10 @@ export default class SelectWallet extends Component { {loc.transactionTimeToReadable(item.getLatestTransactionTime())} @@ -134,18 +161,35 @@ export default class SelectWallet extends Component { render() { if (this.state.isLoading) { return ( - + ); } else if (this.state.data.length <= 0) { return ( - - There are currently no Bitcoin wallets available. + + + There are currently no Bitcoin wallets available. + - - A Bitcoin wallet is required to refill Lightning wallets. Please, create or import one. + + A Bitcoin wallet is required to refill Lightning wallets. Please, + create or import one. @@ -171,6 +215,6 @@ SelectWallet.propTypes = { navigate: PropTypes.func, goBack: PropTypes.func, setParams: PropTypes.func, - getParam: PropTypes.func, - }), + getParam: PropTypes.func + }) }; diff --git a/screen/wallets/transactions.js b/screen/wallets/transactions.js index d497885bf79..34524153cae 100644 --- a/screen/wallets/transactions.js +++ b/screen/wallets/transactions.js @@ -1,6 +1,6 @@ /* global alert */ -import React, { Component } from 'react'; -import { Chain } from '../../models/bitcoinUnits'; +import React, { Component } from "react"; +import { Chain } from "../../models/bitcoinUnits"; import { Text, Platform, @@ -15,10 +15,10 @@ import { TouchableOpacity, StatusBar, Linking, - KeyboardAvoidingView, -} from 'react-native'; -import PropTypes from 'prop-types'; -import { NavigationEvents } from 'react-navigation'; + KeyboardAvoidingView +} from "react-native"; +import PropTypes from "prop-types"; +import { NavigationEvents } from "react-navigation"; import { BlueSendButtonIcon, BlueListItem, @@ -26,42 +26,54 @@ import { BlueTransactionListItem, BlueWalletNavigationHeader, BlueSpacing10, - BlueSpacing40, -} from '../../BlueComponents'; -import WalletGradient from '../../class/walletGradient'; -import { Icon } from 'react-native-elements'; -import Handoff from 'react-native-handoff'; -import Modal from 'react-native-modal'; -import NavigationService from '../../NavigationService'; + BlueSpacing40 +} from "../../BlueComponents"; +import WalletGradient from "../../class/walletGradient"; +import { Icon } from "react-native-elements"; +import Handoff from "react-native-handoff"; +import Modal from "react-native-modal"; +import NavigationService from "../../NavigationService"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); -let EV = require('../../events'); -let BlueElectrum = require('../../BlueElectrum'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); +const EV = require("../../events"); +const BlueElectrum = require("../../BlueElectrum"); export default class WalletTransactions extends Component { static navigationOptions = ({ navigation }) => { return { headerRight: ( - navigation.navigate('WalletDetails', { - wallet: navigation.state.params.wallet, + navigation.navigate("WalletDetails", { + wallet: navigation.state.params.wallet }) } > - + ), headerStyle: { - backgroundColor: WalletGradient.headerColorFor(navigation.state.params.wallet.type), + backgroundColor: WalletGradient.headerColorFor( + navigation.state.params.wallet.type + ), borderBottomWidth: 0, elevation: 0, - shadowRadius: 0, + shadowRadius: 0 }, - headerTintColor: '#ffffff', + headerTintColor: "#ffffff" }; }; @@ -71,8 +83,11 @@ export default class WalletTransactions extends Component { super(props); // here, when we receive REMOTE_TRANSACTIONS_COUNT_CHANGED we fetch TXs and balance for current wallet - EV(EV.enum.REMOTE_TRANSACTIONS_COUNT_CHANGED, this.refreshTransactionsFunction.bind(this)); - const wallet = props.navigation.getParam('wallet'); + EV( + EV.enum.REMOTE_TRANSACTIONS_COUNT_CHANGED, + this.refreshTransactionsFunction.bind(this) + ); + const wallet = props.navigation.getParam("wallet"); this.props.navigation.setParams({ wallet: wallet, isLoading: true }); this.state = { isLoading: true, @@ -81,7 +96,7 @@ export default class WalletTransactions extends Component { wallet: wallet, dataSource: this.getTransactions(15), limit: 15, - pageSize: 20, + pageSize: 20 }; } @@ -93,7 +108,7 @@ export default class WalletTransactions extends Component { * Forcefully fetches TXs and balance for wallet */ refreshTransactionsFunction() { - let that = this; + const that = this; setTimeout(function() { that.refreshTransactions(); }, 4000); // giving a chance to remote server to propagate @@ -107,9 +122,9 @@ export default class WalletTransactions extends Component { * @returns {Array} */ getTransactions(limit = Infinity) { - let wallet = this.props.navigation.getParam('wallet'); + const wallet = this.props.navigation.getParam("wallet"); let txs = wallet.getTransactions(); - for (let tx of txs) { + for (const tx of txs) { tx.sort_ts = +new Date(tx.received); } txs = txs.sort(function(a, b) { @@ -120,12 +135,12 @@ export default class WalletTransactions extends Component { redrawScreen() { InteractionManager.runAfterInteractions(async () => { - console.log('wallets/transactions redrawScreen()'); + console.log("wallets/transactions redrawScreen()"); this.setState({ isLoading: false, showShowFlatListRefreshControl: false, - dataSource: this.getTransactions(this.state.limit), + dataSource: this.getTransactions(this.state.limit) }); }); } @@ -138,7 +153,7 @@ export default class WalletTransactions extends Component { this.setState( { showShowFlatListRefreshControl: true, - isLoading: true, + isLoading: true }, async () => { let noErr = true; @@ -147,14 +162,19 @@ export default class WalletTransactions extends Component { await BlueElectrum.ping(); await BlueElectrum.waitTillConnected(); /** @type {LegacyWallet} */ - let wallet = this.state.wallet; - let balanceStart = +new Date(); + const wallet = this.state.wallet; + const balanceStart = +new Date(); const oldBalance = wallet.getBalance(); await wallet.fetchBalance(); if (oldBalance !== wallet.getBalance()) smthChanged = true; - let balanceEnd = +new Date(); - console.log(wallet.getLabel(), 'fetch balance took', (balanceEnd - balanceStart) / 1000, 'sec'); - let start = +new Date(); + const balanceEnd = +new Date(); + console.log( + wallet.getLabel(), + "fetch balance took", + (balanceEnd - balanceStart) / 1000, + "sec" + ); + const start = +new Date(); const oldTxLen = wallet.getTransactions().length; await wallet.fetchTransactions(); if (wallet.fetchPendingTransactions) { @@ -164,23 +184,28 @@ export default class WalletTransactions extends Component { await wallet.fetchUserInvoices(); } if (oldTxLen !== wallet.getTransactions().length) smthChanged = true; - let end = +new Date(); - console.log(wallet.getLabel(), 'fetch tx took', (end - start) / 1000, 'sec'); + const end = +new Date(); + console.log( + wallet.getLabel(), + "fetch tx took", + (end - start) / 1000, + "sec" + ); } catch (err) { noErr = false; alert(err.message); this.setState({ isLoading: false, - showShowFlatListRefreshControl: false, + showShowFlatListRefreshControl: false }); } if (noErr && smthChanged) { - console.log('saving to disk'); + console.log("saving to disk"); await BlueApp.saveToDisk(); // caching EV(EV.enum.TRANSACTIONS_COUNT_CHANGED); // let other components know they should redraw } this.redrawScreen(); - }, + } ); } @@ -188,21 +213,25 @@ export default class WalletTransactions extends Component { renderListFooterComponent = () => { // if not all txs rendered - display indicator - return (this.getTransactions(Infinity).length > this.state.limit && ) || ; + return ( + (this.getTransactions(Infinity).length > this.state.limit && ( + + )) || + ); }; renderListHeaderComponent = () => { return ( - + {loc.transactions.list.tabBarLabel} @@ -213,8 +242,8 @@ export default class WalletTransactions extends Component { onWalletSelect = async wallet => { if (wallet) { - NavigationService.navigate('WalletTransactions', { - key: `WalletTransactions-${wallet.getID()}`, + NavigationService.navigate("WalletTransactions", { + key: `WalletTransactions-${wallet.getID()}` }); /** @type {LightningCustodianWallet} */ let toAddress = false; @@ -228,17 +257,17 @@ export default class WalletTransactions extends Component { return alert(Err.message); } } - this.props.navigation.navigate('SendDetails', { + this.props.navigation.navigate("SendDetails", { memo: loc.lnd.refill_lnd_balance, fromSecret: wallet.getSecret(), address: toAddress, - fromWallet: wallet, + fromWallet: wallet }); } }; async onWillBlur() { - StatusBar.setBarStyle('dark-content'); + StatusBar.setBarStyle("dark-content"); } componentWillUnmount() { @@ -246,31 +275,44 @@ export default class WalletTransactions extends Component { } renderItem = item => { - return ; + return ( + + ); }; render() { const { navigate } = this.props.navigation; return ( - + {this.state.wallet.chain === Chain.ONCHAIN} { - StatusBar.setBarStyle('light-content'); + StatusBar.setBarStyle("light-content"); this.redrawScreen(); }} onWillBlur={() => this.onWillBlur()} - onDidFocus={() => this.props.navigation.setParams({ isLoading: false })} + onDidFocus={() => + this.props.navigation.setParams({ isLoading: false }) + } /> InteractionManager.runAfterInteractions(async () => { - this.setState({ wallet }, () => InteractionManager.runAfterInteractions(() => BlueApp.saveToDisk())); + this.setState({ wallet }, () => + InteractionManager.runAfterInteractions(() => + BlueApp.saveToDisk() + ) + ); }) } /> - + { @@ -283,21 +325,30 @@ export default class WalletTransactions extends Component { } this.setState({ - dataSource: this.getTransactions(this.state.limit + this.state.pageSize), + dataSource: this.getTransactions( + this.state.limit + this.state.pageSize + ), limit: this.state.limit + this.state.pageSize, - pageSize: this.state.pageSize * 2, + pageSize: this.state.pageSize * 2 }); }} ListHeaderComponent={this.renderListHeaderComponent} ListFooterComponent={this.renderListFooterComponent} ListEmptyComponent={ - + {true && loc.wallets.list.empty_txs1} @@ -305,8 +356,8 @@ export default class WalletTransactions extends Component { {true && loc.wallets.list.empty_txs2} @@ -317,7 +368,10 @@ export default class WalletTransactions extends Component { } refreshControl={ - this.refreshTransactions()} refreshing={this.state.showShowFlatListRefreshControl} /> + this.refreshTransactions()} + refreshing={this.state.showShowFlatListRefreshControl} + /> } extraData={this.state.dataSource} data={this.state.dataSource} @@ -328,14 +382,14 @@ export default class WalletTransactions extends Component { {(() => { @@ -343,7 +397,9 @@ export default class WalletTransactions extends Component { return ( { - navigate('ReceiveDetails', { secret: this.state.wallet.getSecret() }); + navigate("ReceiveDetails", { + secret: this.state.wallet.getSecret() + }); }} /> ); @@ -355,13 +411,12 @@ export default class WalletTransactions extends Component { return ( { - navigate('SendDetails', { - fromAddress: this.state.wallet.getAddress(), - fromSecret: this.state.wallet.getSecret(), - fromWallet: this.state.wallet, - }); - } - } + navigate("SendDetails", { + fromAddress: this.state.wallet.getAddress(), + fromSecret: this.state.wallet.getSecret(), + fromWallet: this.state.wallet + }); + }} /> ); } @@ -376,26 +431,26 @@ const styles = StyleSheet.create({ modalContent: { backgroundColor: BlueApp.settings.brandingColor, padding: 22, - justifyContent: 'center', - alignItems: 'center', + justifyContent: "center", + alignItems: "center", borderTopLeftRadius: 16, borderTopRightRadius: 16, - borderColor: 'rgba(0, 0, 0, 0.1)', + borderColor: "rgba(0, 0, 0, 0.1)", minHeight: 200, - height: 200, + height: 200 }, advancedTransactionOptionsModalContent: { backgroundColor: BlueApp.settings.brandingColor, padding: 22, borderTopLeftRadius: 16, borderTopRightRadius: 16, - borderColor: 'rgba(0, 0, 0, 0.1)', - minHeight: 130, + borderColor: "rgba(0, 0, 0, 0.1)", + minHeight: 130 }, bottomModal: { - justifyContent: 'flex-end', - margin: 0, - }, + justifyContent: "flex-end", + margin: 0 + } }); WalletTransactions.propTypes = { @@ -403,6 +458,6 @@ WalletTransactions.propTypes = { navigate: PropTypes.func, goBack: PropTypes.func, getParam: PropTypes.func, - setParams: PropTypes.func, - }), + setParams: PropTypes.func + }) }; diff --git a/screen/wallets/walletMigrate.js b/screen/wallets/walletMigrate.js index f2d8f357800..6791d9d9b39 100644 --- a/screen/wallets/walletMigrate.js +++ b/screen/wallets/walletMigrate.js @@ -1,9 +1,11 @@ -import AsyncStorage from '@react-native-community/async-storage'; -import RNFS from 'react-native-fs'; -import RNSecureKeyStore, { ACCESSIBLE } from 'react-native-secure-key-store'; +import AsyncStorage from "@react-native-community/async-storage"; +import RNFS from "react-native-fs"; +import RNSecureKeyStore, { ACCESSIBLE } from "react-native-secure-key-store"; export default class WalletMigrate { - static expoDataDirectory = RNFS.DocumentDirectoryPath + '/ExponentExperienceData/%40overtorment%2Fbluewallet/RCTAsyncLocalStorage'; + static expoDataDirectory = + RNFS.DocumentDirectoryPath + + "/ExponentExperienceData/%40overtorment%2Fbluewallet/RCTAsyncLocalStorage"; constructor(onComplete) { this.onComplete = onComplete; @@ -16,53 +18,73 @@ export default class WalletMigrate { // 1: Migrate Document directory from Expo async migrateDataFromExpo() { - const expoDirectoryExists = await RNFS.exists(RNFS.DocumentDirectoryPath + '/ExponentExperienceData'); + const expoDirectoryExists = await RNFS.exists( + RNFS.DocumentDirectoryPath + "/ExponentExperienceData" + ); if (!expoDirectoryExists) { - console.log('Expo data was previously migrated. Exiting migration...'); + console.log("Expo data was previously migrated. Exiting migration..."); await this.migrateDataToSecureKeystore(); return; } try { - await RNFS.unlink(RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1'); - console.log('/RCTAsyncLocalStorage_V1 has been deleted. Continuing...'); + await RNFS.unlink( + RNFS.DocumentDirectoryPath + "/RCTAsyncLocalStorage_V1" + ); + console.log("/RCTAsyncLocalStorage_V1 has been deleted. Continuing..."); } catch (error) { console.log(error); - console.log('/RCTAsyncLocalStorage_V1 does not exist. Continuing...'); + console.log("/RCTAsyncLocalStorage_V1 does not exist. Continuing..."); } try { - await RNFS.copyFile(WalletMigrate.expoDataDirectory, RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1'); + await RNFS.copyFile( + WalletMigrate.expoDataDirectory, + RNFS.DocumentDirectoryPath + "/RCTAsyncLocalStorage_V1" + ); } catch (error) { - console.log('An error was encountered when trying to copy Expo data to /RCTAsyncLocalStorage_V1. Exiting migration...'); + console.log( + "An error was encountered when trying to copy Expo data to /RCTAsyncLocalStorage_V1. Exiting migration..." + ); console.log(error); } try { - await RNFS.unlink(RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1/.DS_Store'); + await RNFS.unlink( + RNFS.DocumentDirectoryPath + "/RCTAsyncLocalStorage_V1/.DS_Store" + ); } catch (error) { - console.log('An error was encountered when trying to delete .DS_Store. Continuing migration...'); + console.log( + "An error was encountered when trying to delete .DS_Store. Continuing migration..." + ); console.log(error); } const files = await RNFS.readDir(WalletMigrate.expoDataDirectory); for (const file of files) { try { if (file.isFile()) { - if (file.name === 'manifest.json') { + if (file.name === "manifest.json") { const manifestFile = await RNFS.readFile(file.path); const manifestFileParsed = JSON.parse(manifestFile); - if (manifestFileParsed.hasOwnProperty('data')) { - if (typeof manifestFileParsed.data === 'string') { - await AsyncStorage.setItem('data', manifestFileParsed.data); + if (manifestFileParsed.hasOwnProperty("data")) { + if (typeof manifestFileParsed.data === "string") { + await AsyncStorage.setItem("data", manifestFileParsed.data); } } - if (manifestFileParsed.hasOwnProperty('data_encrypted')) { - if (typeof manifestFileParsed.data_encrypted === 'string') { - await AsyncStorage.setItem('data_encrypted', manifestFileParsed.data_encrypted); + if (manifestFileParsed.hasOwnProperty("data_encrypted")) { + if (typeof manifestFileParsed.data_encrypted === "string") { + await AsyncStorage.setItem( + "data_encrypted", + manifestFileParsed.data_encrypted + ); } } - } else if (file.name !== 'manifest.json') { + } else if (file.name !== "manifest.json") { const manifestFile = await RNFS.readFile(file.path); const manifestFileParsed = JSON.parse(manifestFile); - if (typeof manifestFileParsed === 'object') await AsyncStorage.setItem('data', JSON.stringify(manifestFileParsed)); + if (typeof manifestFileParsed === "object") + await AsyncStorage.setItem( + "data", + JSON.stringify(manifestFileParsed) + ); } } } catch (error) { @@ -70,10 +92,12 @@ export default class WalletMigrate { } } try { - await RNFS.unlink(RNFS.DocumentDirectoryPath + '/ExponentExperienceData'); - console.log('Deleted /ExponentExperienceData.'); + await RNFS.unlink(RNFS.DocumentDirectoryPath + "/ExponentExperienceData"); + console.log("Deleted /ExponentExperienceData."); } catch (error) { - console.log('An error was encountered when trying to delete /ExponentExperienceData. Exiting migration...'); + console.log( + "An error was encountered when trying to delete /ExponentExperienceData. Exiting migration..." + ); console.log(error); } await this.migrateDataToSecureKeystore(); @@ -82,25 +106,28 @@ export default class WalletMigrate { // 2: Migrate Data from AsyncStorage to RNSecureKeyStore async migrateDataToSecureKeystore() { try { - const data = await AsyncStorage.getItem('data'); + const data = await AsyncStorage.getItem("data"); if (data) { - const isEncrypted = (await AsyncStorage.getItem('data_encrypted')) || ''; - await RNSecureKeyStore.set('data', data, { accessible: ACCESSIBLE.WHEN_UNLOCKED }); - await RNSecureKeyStore.set('data_encrypted', isEncrypted, { - accessible: ACCESSIBLE.WHEN_UNLOCKED, + const isEncrypted = + (await AsyncStorage.getItem("data_encrypted")) || ""; + await RNSecureKeyStore.set("data", data, { + accessible: ACCESSIBLE.WHEN_UNLOCKED }); - await AsyncStorage.removeItem('data'); - await AsyncStorage.removeItem('data_encrypted'); + await RNSecureKeyStore.set("data_encrypted", isEncrypted, { + accessible: ACCESSIBLE.WHEN_UNLOCKED + }); + await AsyncStorage.removeItem("data"); + await AsyncStorage.removeItem("data_encrypted"); } } catch (_e) { - console.log('Nothing to migrate from AsyncStorage.'); + console.log("Nothing to migrate from AsyncStorage."); } this.migrationComplete(); } // 3: We're done! migrationComplete() { - console.log('Migration was successful. Exiting migration...'); + console.log("Migration was successful. Exiting migration..."); this.onComplete(); } } diff --git a/screen/wallets/xpub.js b/screen/wallets/xpub.js index 2a0bdb1bacc..2099ca3b920 100644 --- a/screen/wallets/xpub.js +++ b/screen/wallets/xpub.js @@ -1,29 +1,38 @@ -import React, { Component } from 'react'; -import { Dimensions, ActivityIndicator, View } from 'react-native'; -import QRCode from 'react-native-qrcode-svg'; -import { BlueSpacing20, SafeBlueArea, BlueText, BlueNavigationStyle, BlueCopyTextToClipboard } from '../../BlueComponents'; -import PropTypes from 'prop-types'; -import Privacy from '../../Privacy'; -import Biometric from '../../class/biometrics'; +import React, { Component } from "react"; +import { Dimensions, ActivityIndicator, View } from "react-native"; +import QRCode from "react-native-qrcode-svg"; +import { + BlueSpacing20, + SafeBlueArea, + BlueText, + BlueNavigationStyle, + BlueCopyTextToClipboard +} from "../../BlueComponents"; +import PropTypes from "prop-types"; +import Privacy from "../../Privacy"; +import Biometric from "../../class/biometrics"; /** @type {AppStorage} */ -let BlueApp = require('../../BlueApp'); -let loc = require('../../loc'); -const { height, width } = Dimensions.get('window'); +const BlueApp = require("../../BlueApp"); +const loc = require("../../loc"); + +const { height, width } = Dimensions.get("window"); export default class WalletXpub extends Component { static navigationOptions = ({ navigation }) => ({ ...BlueNavigationStyle(navigation, true), - title: loc.wallets.xpub.title.slice(0,1).toUpperCase() + loc.wallets.xpub.title.slice(1, loc.wallets.xpub.title.length), - headerLeft: null, + title: + loc.wallets.xpub.title.slice(0, 1).toUpperCase() + + loc.wallets.xpub.title.slice(1, loc.wallets.xpub.title.length), + headerLeft: null }); constructor(props) { super(props); - let secret = props.navigation.state.params.secret; + const secret = props.navigation.state.params.secret; let wallet; - for (let w of BlueApp.getWallets()) { + for (const w of BlueApp.getWallets()) { if (w.getSecret() === secret) { // found our wallet wallet = w; @@ -35,7 +44,7 @@ export default class WalletXpub extends Component { wallet, xpub: wallet.getXpub(), xpubText: wallet.getXpub(), - qrCodeHeight: height > width ? width - 40 : width / 2, + qrCodeHeight: height > width ? width - 40 : width / 2 }; } @@ -50,7 +59,7 @@ export default class WalletXpub extends Component { } this.setState({ - isLoading: false, + isLoading: false }); } @@ -59,7 +68,7 @@ export default class WalletXpub extends Component { } onLayout = () => { - const { height } = Dimensions.get('window'); + const { height } = Dimensions.get("window"); this.setState({ qrCodeHeight: height > width ? width - 40 : width / 2 }); }; @@ -74,20 +83,23 @@ export default class WalletXpub extends Component { return ( - + {this.state.wallet.typeReadable} - + @@ -101,10 +113,10 @@ WalletXpub.propTypes = { navigation: PropTypes.shape({ state: PropTypes.shape({ params: PropTypes.shape({ - secret: PropTypes.string, - }), + secret: PropTypes.string + }) }), navigate: PropTypes.func, - goBack: PropTypes.func, - }), + goBack: PropTypes.func + }) }; diff --git a/shim.js b/shim.js index 8fa67a285e6..3ad00f8b4db 100644 --- a/shim.js +++ b/shim.js @@ -1,12 +1,13 @@ /* global __DEV__, localStorage */ -global.net = require('react-native-tcp'); -if (typeof __dirname === 'undefined') global.__dirname = '/'; -if (typeof __filename === 'undefined') global.__filename = ''; -if (typeof process === 'undefined') { - global.process = require('process'); +global.net = require("react-native-tcp"); + +if (typeof __dirname === "undefined") global.__dirname = "/"; +if (typeof __filename === "undefined") global.__filename = ""; +if (typeof process === "undefined") { + global.process = require("process"); } else { - const bProcess = require('process'); - for (var p in bProcess) { + const bProcess = require("process"); + for (const p in bProcess) { if (!(p in process)) { process[p] = bProcess[p]; } @@ -14,11 +15,11 @@ if (typeof process === 'undefined') { } process.browser = false; -if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer; +if (typeof Buffer === "undefined") global.Buffer = require("buffer").Buffer; // global.location = global.location || { port: 80 } -const isDev = typeof __DEV__ === 'boolean' && __DEV__; -process.env['NODE_ENV'] = isDev ? 'development' : 'production'; -if (typeof localStorage !== 'undefined') { - localStorage.debug = isDev ? '*' : ''; +const isDev = typeof __DEV__ === "boolean" && __DEV__; +process.env["NODE_ENV"] = isDev ? "development" : "production"; +if (typeof localStorage !== "undefined") { + localStorage.debug = isDev ? "*" : ""; } diff --git a/tests/integration/App.test.js b/tests/integration/App.test.js index 4372ddbadde..3ffe4798c9e 100644 --- a/tests/integration/App.test.js +++ b/tests/integration/App.test.js @@ -1,87 +1,89 @@ /* global describe, it, expect, jest, jasmine */ -import React from 'react'; -import { LegacyWallet, SegwitP2SHWallet, AppStorage } from '../../class'; -import TestRenderer from 'react-test-renderer'; -import Settings from '../../screen/settings/settings'; -import Selftest from '../../screen/selftest'; -import { BlueHeader } from '../../BlueComponents'; -import { FiatUnit } from '../../models/fiatUnit'; -import AsyncStorage from '@react-native-community/async-storage'; -global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment -let assert = require('assert'); -jest.mock('react-native-qrcode-svg', () => 'Video'); +import React from "react"; +import { LegacyWallet, SegwitP2SHWallet, AppStorage } from "../../class"; +import TestRenderer from "react-test-renderer"; +import Settings from "../../screen/settings/settings"; +import Selftest from "../../screen/selftest"; +import { BlueHeader } from "../../BlueComponents"; +import { FiatUnit } from "../../models/fiatUnit"; +import AsyncStorage from "@react-native-community/async-storage"; + +global.crypto = require("crypto"); // shall be used by tests under nodejs CLI, but not in RN environment +const assert = require("assert"); + +jest.mock("react-native-qrcode-svg", () => "Video"); jest.useFakeTimers(); -jest.mock('Picker', () => { +jest.mock("Picker", () => { // eslint-disable-next-line import/no-unresolved - const React = require('React'); - const PropTypes = require('prop-types'); + const React = require("React"); + const PropTypes = require("prop-types"); return class MockPicker extends React.Component { - static Item = props => React.createElement('Item', props, props.children); + static Item = props => React.createElement("Item", props, props.children); static propTypes = { children: PropTypes.any }; - static defaultProps = { children: '' }; + static defaultProps = { children: "" }; render() { - return React.createElement('Picker', this.props, this.props.children); + return React.createElement("Picker", this.props, this.props.children); } }; }); -jest.mock('amplitude-js', () => ({ +jest.mock("amplitude-js", () => ({ getInstance: function() { return { init: jest.fn(), - logEvent: jest.fn(), + logEvent: jest.fn() }; - }, + } })); -jest.mock('ScrollView', () => { - const RealComponent = require.requireActual('ScrollView'); - const React = require('React'); +jest.mock("ScrollView", () => { + const RealComponent = require.requireActual("ScrollView"); + const React = require("React"); class ScrollView extends React.Component { scrollTo() {} render() { - return React.createElement('ScrollView', this.props, this.props.children); + return React.createElement("ScrollView", this.props, this.props.children); } } ScrollView.propTypes = RealComponent.propTypes; return ScrollView; }); -describe('unit - LegacyWallet', function() { - it('serialize and unserialize work correctly', () => { - let a = new LegacyWallet(); - a.setLabel('my1'); - let key = JSON.stringify(a); +describe("unit - LegacyWallet", function() { + it("serialize and unserialize work correctly", () => { + const a = new LegacyWallet(); + a.setLabel("my1"); + const key = JSON.stringify(a); - let b = LegacyWallet.fromJson(key); + const b = LegacyWallet.fromJson(key); assert(key === JSON.stringify(b)); assert.strictEqual(key, JSON.stringify(b)); }); - it('can validate addresses', () => { - let w = new LegacyWallet(); - assert.ok(w.isAddressValid('12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG')); - assert.ok(!w.isAddressValid('12eQ9m4sgAwTSQoNXkRABKhCXCsjm2j')); - assert.ok(w.isAddressValid('3BDsBDxDimYgNZzsqszNZobqQq3yeUoJf2')); - assert.ok(!w.isAddressValid('3BDsBDxDimYgNZzsqszNZobqQq3yeUo')); - assert.ok(!w.isAddressValid('12345')); + it("can validate addresses", () => { + const w = new LegacyWallet(); + assert.ok(w.isAddressValid("12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG")); + assert.ok(!w.isAddressValid("12eQ9m4sgAwTSQoNXkRABKhCXCsjm2j")); + assert.ok(w.isAddressValid("3BDsBDxDimYgNZzsqszNZobqQq3yeUoJf2")); + assert.ok(!w.isAddressValid("3BDsBDxDimYgNZzsqszNZobqQq3yeUo")); + assert.ok(!w.isAddressValid("12345")); }); }); -it('BlueHeader works', () => { +it("BlueHeader works", () => { const rendered = TestRenderer.create().toJSON(); expect(rendered).toBeTruthy(); }); -it.skip('Settings work', () => { +it.skip("Settings work", () => { const rendered = TestRenderer.create().toJSON(); expect(rendered).toBeTruthy(); }); -it('Selftest work', () => { +it("Selftest work", () => { const component = TestRenderer.create(); const root = component.root; const rendered = component.toJSON(); @@ -89,41 +91,44 @@ it('Selftest work', () => { // console.log((root.findAllByType('Text')[0].props)); let okFound = false; - let allTests = []; - for (var v of root.findAllByType('Text')) { + const allTests = []; + for (const v of root.findAllByType("Text")) { let text = v.props.children; if (text.join) { - text = text.join(''); + text = text.join(""); } - if (text === 'OK') { + if (text === "OK") { okFound = true; } allTests.push(text); // console.log(text); } - assert.ok(okFound, 'OK not found. Got: ' + allTests.join('; ')); + assert.ok(okFound, "OK not found. Got: " + allTests.join("; ")); }); -it('Wallet can fetch UTXO', async () => { +it("Wallet can fetch UTXO", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; - let w = new SegwitP2SHWallet(); - w._address = '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX'; + const w = new SegwitP2SHWallet(); + w._address = "12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX"; await w.fetchUtxo(); - assert.ok(w.utxo.length > 0, 'unexpected empty UTXO'); + assert.ok(w.utxo.length > 0, "unexpected empty UTXO"); }); -it('SegwitP2SHWallet can generate segwit P2SH address from WIF', async () => { - let l = new SegwitP2SHWallet(); - l.setSecret('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct'); - assert.ok(l.getAddress() === '34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53', 'expected ' + l.getAddress()); +it("SegwitP2SHWallet can generate segwit P2SH address from WIF", async () => { + const l = new SegwitP2SHWallet(); + l.setSecret("Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct"); + assert.ok( + l.getAddress() === "34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53", + "expected " + l.getAddress() + ); assert.ok(l.getAddress() === (await l.getAddressAsync())); }); -it('Wallet can fetch balance', async () => { +it("Wallet can fetch balance", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; - let w = new LegacyWallet(); - w._address = '115fUy41sZkAG14CmdP1VbEKcNRZJWkUWG'; // hack internals + const w = new LegacyWallet(); + w._address = "115fUy41sZkAG14CmdP1VbEKcNRZJWkUWG"; // hack internals assert.ok(w.getBalance() === 0); assert.ok(w.getUnconfirmedBalance() === 0); assert.ok(w._lastBalanceFetch === 0); @@ -133,26 +138,30 @@ it('Wallet can fetch balance', async () => { assert.ok(w._lastBalanceFetch > 0); }); -it('Wallet can fetch TXs', async () => { - let w = new LegacyWallet(); - w._address = '12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG'; +it("Wallet can fetch TXs", async () => { + const w = new LegacyWallet(); + w._address = "12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG"; await w.fetchTransactions(); assert.strictEqual(w.getTransactions().length, 2); - let tx0 = w.getTransactions()[0]; - let txExpected = { - block_hash: '0000000000000000000d05c54a592db8532f134e12b4c3ae0821ce582fad3566', + const tx0 = w.getTransactions()[0]; + const txExpected = { + block_hash: + "0000000000000000000d05c54a592db8532f134e12b4c3ae0821ce582fad3566", block_height: 530933, block_index: 1587, - hash: '4924f3a29acdee007ebcf6084d2c9e1752c4eb7f26f7d1a06ef808780bf5fe6d', - addresses: ['12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG', '3BDsBDxDimYgNZzsqszNZobqQq3yeUoJf2'], + hash: "4924f3a29acdee007ebcf6084d2c9e1752c4eb7f26f7d1a06ef808780bf5fe6d", + addresses: [ + "12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG", + "3BDsBDxDimYgNZzsqszNZobqQq3yeUoJf2" + ], total: 800, fees: 200, size: 190, - preference: 'low', - relayed_by: '18.197.135.148:8333', - confirmed: '2018-07-07T20:05:30Z', - received: '2018-07-07T20:02:01.637Z', + preference: "low", + relayed_by: "18.197.135.148:8333", + confirmed: "2018-07-07T20:05:30Z", + received: "2018-07-07T20:02:01.637Z", ver: 1, double_spend: false, vin_sz: 1, @@ -161,27 +170,29 @@ it('Wallet can fetch TXs', async () => { confidence: 1, inputs: [ { - prev_hash: 'd0432027a86119c63a0be8fa453275c2333b59067f1e559389cd3e0e377c8b96', + prev_hash: + "d0432027a86119c63a0be8fa453275c2333b59067f1e559389cd3e0e377c8b96", output_index: 1, script: - '483045022100e443784abe25b6d39e01c95900834bf4eeaa82505ac0eb84c08e11c287d467de02203327c2b1136f4976f755ed7631b427d66db2278414e7faf1268eedf44c034e0c012103c69b905f7242b3688122f06951339a1ee00da652f6ecc6527ea6632146cace62', + "483045022100e443784abe25b6d39e01c95900834bf4eeaa82505ac0eb84c08e11c287d467de02203327c2b1136f4976f755ed7631b427d66db2278414e7faf1268eedf44c034e0c012103c69b905f7242b3688122f06951339a1ee00da652f6ecc6527ea6632146cace62", output_value: 1000, sequence: 4294967295, - addresses: ['12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG'], - script_type: 'pay-to-pubkey-hash', - age: 530926, - }, + addresses: ["12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG"], + script_type: "pay-to-pubkey-hash", + age: 530926 + } ], outputs: [ { value: 800, - script: 'a914688eb9af71aab8ca221f4e6171a45fc46ea8743b87', - spent_by: '009c6219deeac341833642193e4a3b72e511105a61b48e375c5025b1bcbd6fb5', - addresses: ['3BDsBDxDimYgNZzsqszNZobqQq3yeUoJf2'], - script_type: 'pay-to-script-hash', - }, + script: "a914688eb9af71aab8ca221f4e6171a45fc46ea8743b87", + spent_by: + "009c6219deeac341833642193e4a3b72e511105a61b48e375c5025b1bcbd6fb5", + addresses: ["3BDsBDxDimYgNZzsqszNZobqQq3yeUoJf2"], + script_type: "pay-to-script-hash" + } ], - value: -1000, + value: -1000 }; delete tx0.confirmations; @@ -191,29 +202,32 @@ it('Wallet can fetch TXs', async () => { assert.deepStrictEqual(tx0, txExpected); }); -describe('currency', () => { - it('fetches exchange rate and saves to AsyncStorage', async () => { +describe("currency", () => { + it("fetches exchange rate and saves to AsyncStorage", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 15000; - let currency = require('../../currency'); + const currency = require("../../currency"); await currency.startUpdater(); let cur = await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES); cur = JSON.parse(cur); assert.ok(Number.isInteger(cur[currency.STRUCT.LAST_UPDATED])); assert.ok(cur[currency.STRUCT.LAST_UPDATED] > 0); - assert.ok(cur['BTC_USD'] > 0); + assert.ok(cur["BTC_USD"] > 0); // now, setting other currency as default - await AsyncStorage.setItem(AppStorage.PREFERRED_CURRENCY, JSON.stringify(FiatUnit.JPY)); + await AsyncStorage.setItem( + AppStorage.PREFERRED_CURRENCY, + JSON.stringify(FiatUnit.JPY) + ); await currency.startUpdater(); cur = JSON.parse(await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES)); - assert.ok(cur['BTC_JPY'] > 0); + assert.ok(cur["BTC_JPY"] > 0); // now setting with a proper setter await currency.setPrefferedCurrency(FiatUnit.EUR); await currency.startUpdater(); - let preferred = await currency.getPreferredCurrency(); - assert.strictEqual(preferred.endPointKey, 'EUR'); + const preferred = await currency.getPreferredCurrency(); + assert.strictEqual(preferred.endPointKey, "EUR"); cur = JSON.parse(await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES)); - assert.ok(cur['BTC_EUR'] > 0); + assert.ok(cur["BTC_EUR"] > 0); }); }); diff --git a/tests/integration/Bip38.test.js b/tests/integration/Bip38.test.js index 7abb5aaa4aa..a7f96743a8c 100644 --- a/tests/integration/Bip38.test.js +++ b/tests/integration/Bip38.test.js @@ -1,38 +1,46 @@ /* global it, jasmine */ -let assert = require('assert'); +const assert = require("assert"); -it('bip38 decodes', async () => { - const bip38 = require('../../bip38'); - const wif = require('wif'); +it("bip38 decodes", async () => { + const bip38 = require("../../bip38"); + const wif = require("wif"); - let encryptedKey = '6PRVWUbkzq2VVjRuv58jpwVjTeN46MeNmzUHqUjQptBJUHGcBakduhrUNc'; - let decryptedKey = await bip38.decrypt( + const encryptedKey = + "6PRVWUbkzq2VVjRuv58jpwVjTeN46MeNmzUHqUjQptBJUHGcBakduhrUNc"; + const decryptedKey = await bip38.decrypt( encryptedKey, - 'TestingOneTwoThree', + "TestingOneTwoThree", () => {}, - { N: 1, r: 8, p: 8 }, // using non-default parameters to speed it up (not-bip38 compliant) + { N: 1, r: 8, p: 8 } // using non-default parameters to speed it up (not-bip38 compliant) ); assert.strictEqual( wif.encode(0x80, decryptedKey.privateKey, decryptedKey.compressed), - '5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR', + "5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR" ); }); -it('bip38 decodes slow', async () => { - if (process.env.USER === 'burn' || process.env.USER === 'igor' || process.env.USER === 'overtorment') { +it("bip38 decodes slow", async () => { + if ( + process.env.USER === "burn" || + process.env.USER === "igor" || + process.env.USER === "overtorment" + ) { // run only on circleCI return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; - const bip38 = require('../../bip38'); - const wif = require('wif'); + const bip38 = require("../../bip38"); + const wif = require("wif"); - let encryptedKey = '6PnU5voARjBBykwSddwCdcn6Eu9EcsK24Gs5zWxbJbPZYW7eiYQP8XgKbN'; - let decryptedKey = await bip38.decrypt(encryptedKey, 'qwerty', status => process.stdout.write(parseInt(status.percent) + '%\r')); + const encryptedKey = + "6PnU5voARjBBykwSddwCdcn6Eu9EcsK24Gs5zWxbJbPZYW7eiYQP8XgKbN"; + const decryptedKey = await bip38.decrypt(encryptedKey, "qwerty", status => + process.stdout.write(parseInt(status.percent) + "%\r") + ); assert.strictEqual( wif.encode(0x80, decryptedKey.privateKey, decryptedKey.compressed), - 'KxqRtpd9vFju297ACPKHrGkgXuberTveZPXbRDiQ3MXZycSQYtjc', + "KxqRtpd9vFju297ACPKHrGkgXuberTveZPXbRDiQ3MXZycSQYtjc" ); }); diff --git a/tests/integration/Electrum.test.js b/tests/integration/Electrum.test.js index bb6530b106c..12f5a25a7b2 100644 --- a/tests/integration/Electrum.test.js +++ b/tests/integration/Electrum.test.js @@ -1,8 +1,9 @@ /* global it, describe, afterAll, beforeAll, jasmine */ -const bitcoin = require('bitcoinjs-lib'); -global.net = require('net'); -let BlueElectrum = require('../../BlueElectrum'); -let assert = require('assert'); +const bitcoin = require("bitcoinjs-lib"); +global.net = require("net"); +const BlueElectrum = require("../../BlueElectrum"); +const assert = require("assert"); + jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000; afterAll(() => { @@ -17,50 +18,64 @@ beforeAll(async () => { try { await BlueElectrum.waitTillConnected(); } catch (err) { - console.log('failed to connect to Electrum:', err); + console.log("failed to connect to Electrum:", err); process.exit(1); } }); -describe('Electrum', () => { - it('ElectrumClient can test connection', async () => { - assert.ok(await BlueElectrum.testConnection('electrum1.bluewallet.io', '50001')); +describe("Electrum", () => { + it("ElectrumClient can test connection", async () => { + assert.ok( + await BlueElectrum.testConnection("electrum1.bluewallet.io", "50001") + ); }); - it('ElectrumClient can estimate fees', async () => { + it("ElectrumClient can estimate fees", async () => { assert.ok((await BlueElectrum.estimateFee(1)) > 1); }); - it('ElectrumClient can connect and query', async () => { - const ElectrumClient = require('electrum-client'); + it("ElectrumClient can connect and query", async () => { + const ElectrumClient = require("electrum-client"); - for (let peer of BlueElectrum.hardcodedPeers) { - let mainClient = new ElectrumClient(peer.tcp, peer.host, 'tcp'); + for (const peer of BlueElectrum.hardcodedPeers) { + const mainClient = new ElectrumClient(peer.tcp, peer.host, "tcp"); try { await mainClient.connect(); - await mainClient.server_version('2.7.11', '1.4'); + await mainClient.server_version("2.7.11", "1.4"); } catch (e) { mainClient.reconnect = mainClient.keepAlive = () => {}; // dirty hack to make it stop reconnecting mainClient.close(); - throw new Error('bad connection: ' + JSON.stringify(peer) + ' ' + e.message); + throw new Error( + "bad connection: " + JSON.stringify(peer) + " " + e.message + ); } - let addr4elect = 'bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej'; + let addr4elect = + "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej"; let script = bitcoin.address.toOutputScript(addr4elect); let hash = bitcoin.crypto.sha256(script); let reversedHash = Buffer.from(hash.reverse()); - let start = +new Date(); - let balance = await mainClient.blockchainScripthash_getBalance(reversedHash.toString('hex')); - let end = +new Date(); - console.warn(peer.host, 'took', (end - start) / 1000, 'seconds to fetch balance'); + const start = +new Date(); + let balance = await mainClient.blockchainScripthash_getBalance( + reversedHash.toString("hex") + ); + const end = +new Date(); + console.warn( + peer.host, + "took", + (end - start) / 1000, + "seconds to fetch balance" + ); assert.ok(balance.confirmed > 0); - addr4elect = '3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK'; + addr4elect = "3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK"; script = bitcoin.address.toOutputScript(addr4elect); hash = bitcoin.crypto.sha256(script); reversedHash = Buffer.from(hash.reverse()); - balance = await mainClient.blockchainScripthash_getBalance(reversedHash.toString('hex')); + balance = await mainClient.blockchainScripthash_getBalance( + reversedHash.toString("hex") + ); // let peers = await mainClient.serverPeers_subscribe(); // console.log(peers); @@ -69,25 +84,32 @@ describe('Electrum', () => { } }); - it('BlueElectrum can do getBalanceByAddress()', async function() { - let address = '3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK'; - let balance = await BlueElectrum.getBalanceByAddress(address); + it("BlueElectrum can do getBalanceByAddress()", async function() { + const address = "3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK"; + const balance = await BlueElectrum.getBalanceByAddress(address); assert.strictEqual(balance.confirmed, 51432); assert.strictEqual(balance.unconfirmed, 0); assert.strictEqual(balance.addr, address); }); - it('BlueElectrum can do getTransactionsByAddress()', async function() { - let txs = await BlueElectrum.getTransactionsByAddress('bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'); + it("BlueElectrum can do getTransactionsByAddress()", async function() { + const txs = await BlueElectrum.getTransactionsByAddress( + "bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh" + ); assert.strictEqual(txs.length, 1); - assert.strictEqual(txs[0].tx_hash, 'ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d'); + assert.strictEqual( + txs[0].tx_hash, + "ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d" + ); assert.strictEqual(txs[0].height, 563077); }); - it('BlueElectrum can do getTransactionsFullByAddress()', async function() { - let txs = await BlueElectrum.getTransactionsFullByAddress('bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'); - for (let tx of txs) { - assert.ok(tx.address === 'bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'); + it("BlueElectrum can do getTransactionsFullByAddress()", async function() { + const txs = await BlueElectrum.getTransactionsFullByAddress( + "bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh" + ); + for (const tx of txs) { + assert.ok(tx.address === "bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh"); assert.ok(tx.txid); assert.ok(tx.confirmations); assert.ok(!tx.vin); @@ -102,98 +124,159 @@ describe('Electrum', () => { } }); - it('BlueElectrum can do multiGetBalanceByAddress()', async function() { - let balances = await BlueElectrum.multiGetBalanceByAddress([ - 'bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh', - 'bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p', - 'bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r', - 'bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy', + it("BlueElectrum can do multiGetBalanceByAddress()", async function() { + const balances = await BlueElectrum.multiGetBalanceByAddress([ + "bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh", + "bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p", + "bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r", + "bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy" ]); assert.strictEqual(balances.balance, 200000); assert.strictEqual(balances.unconfirmed_balance, 0); - assert.strictEqual(balances.addresses['bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'].confirmed, 50000); - assert.strictEqual(balances.addresses['bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'].unconfirmed, 0); - assert.strictEqual(balances.addresses['bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p'].confirmed, 50000); - assert.strictEqual(balances.addresses['bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p'].unconfirmed, 0); - assert.strictEqual(balances.addresses['bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r'].confirmed, 50000); - assert.strictEqual(balances.addresses['bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r'].unconfirmed, 0); - assert.strictEqual(balances.addresses['bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy'].confirmed, 50000); - assert.strictEqual(balances.addresses['bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy'].unconfirmed, 0); + assert.strictEqual( + balances.addresses["bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh"] + .confirmed, + 50000 + ); + assert.strictEqual( + balances.addresses["bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh"] + .unconfirmed, + 0 + ); + assert.strictEqual( + balances.addresses["bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p"] + .confirmed, + 50000 + ); + assert.strictEqual( + balances.addresses["bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p"] + .unconfirmed, + 0 + ); + assert.strictEqual( + balances.addresses["bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r"] + .confirmed, + 50000 + ); + assert.strictEqual( + balances.addresses["bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r"] + .unconfirmed, + 0 + ); + assert.strictEqual( + balances.addresses["bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy"] + .confirmed, + 50000 + ); + assert.strictEqual( + balances.addresses["bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy"] + .unconfirmed, + 0 + ); }); - it('BlueElectrum can do multiGetUtxoByAddress()', async () => { - let utxos = await BlueElectrum.multiGetUtxoByAddress( + it("BlueElectrum can do multiGetUtxoByAddress()", async () => { + const utxos = await BlueElectrum.multiGetUtxoByAddress( [ - 'bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh', - 'bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p', - 'bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r', - 'bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy', + "bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh", + "bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p", + "bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r", + "bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy" ], - 3, + 3 ); assert.strictEqual(Object.keys(utxos).length, 4); assert.strictEqual( - utxos['bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'][0].txId, - 'ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d', + utxos["bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh"][0].txId, + "ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d" + ); + assert.strictEqual( + utxos["bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh"][0].vout, + 1 + ); + assert.strictEqual( + utxos["bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh"][0].value, + 50000 + ); + assert.strictEqual( + utxos["bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh"][0].address, + "bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh" ); - assert.strictEqual(utxos['bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'][0].vout, 1); - assert.strictEqual(utxos['bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'][0].value, 50000); - assert.strictEqual(utxos['bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'][0].address, 'bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'); }); - it('ElectrumClient can do multiGetHistoryByAddress()', async () => { - let histories = await BlueElectrum.multiGetHistoryByAddress( + it("ElectrumClient can do multiGetHistoryByAddress()", async () => { + const histories = await BlueElectrum.multiGetHistoryByAddress( [ - 'bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh', - 'bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p', - 'bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r', - 'bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy', - 'bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy', // duplicate intended + "bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh", + "bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p", + "bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r", + "bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy", + "bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy" // duplicate intended ], - 3, + 3 ); assert.ok( - histories['bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'][0]['tx_hash'] === - 'ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d', + histories["bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh"][0]["tx_hash"] === + "ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d" ); assert.ok( - histories['bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy'][0]['tx_hash'] === - '5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df', + histories["bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy"][0]["tx_hash"] === + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df" ); assert.ok(Object.keys(histories).length === 4); }); - it('ElectrumClient can do multiGetTransactionByTxid()', async () => { - let txdatas = await BlueElectrum.multiGetTransactionByTxid( + it("ElectrumClient can do multiGetTransactionByTxid()", async () => { + const txdatas = await BlueElectrum.multiGetTransactionByTxid( [ - 'ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d', - '042c9e276c2d06b0b84899771a7f218af90dd60436947c49a844a05d7c104b26', - '2cf439be65e7cc7c6e4db721b1c8fcb1cd95ff07cde79a52a73b3d15a12b2eb6', - '5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df', - '5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df', // duplicate intended + "ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d", + "042c9e276c2d06b0b84899771a7f218af90dd60436947c49a844a05d7c104b26", + "2cf439be65e7cc7c6e4db721b1c8fcb1cd95ff07cde79a52a73b3d15a12b2eb6", + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df", + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df" // duplicate intended ], - 3, + 3 ); assert.ok( - txdatas['ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d'].txid === - 'ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d', + txdatas[ + "ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d" + ].txid === + "ad00a92409d8982a1d7f877056dbed0c4337d2ebab70b30463e2802279fb936d" + ); + assert.ok( + txdatas[ + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df" + ].txid === + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df" + ); + assert.ok( + txdatas[ + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df" + ].size ); assert.ok( - txdatas['5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df'].txid === - '5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df', + txdatas[ + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df" + ].vin + ); + assert.ok( + txdatas[ + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df" + ].vout + ); + assert.ok( + txdatas[ + "5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df" + ].blocktime ); - assert.ok(txdatas['5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df'].size); - assert.ok(txdatas['5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df'].vin); - assert.ok(txdatas['5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df'].vout); - assert.ok(txdatas['5e2fa84148a7389537434b3ad12fcae71ed43ce5fb0f016a7f154a9b99a973df'].blocktime); assert.ok(Object.keys(txdatas).length === 4); }); - it.skip('multiGetTransactionByTxid() can work with huge tx', async () => { + it.skip("multiGetTransactionByTxid() can work with huge tx", async () => { // electrum cant return verbose output because of "response too large (over 1,000,000 bytes" // for example: // echo '[{"jsonrpc":"2.0","method":"blockchain.transaction.get","params":["484a11c5e086a281413b9192b4f60c06abf745f08c2c28c4b4daefe6df3b9e5c", true],"id":1}]' | nc bitkoins.nl 50001 -i 1 @@ -202,20 +285,28 @@ describe('Electrum', () => { // possible solution: fetch it without verbose and decode locally. unfortunatelly it omits such info as confirmations, time etc // so whoever uses it should be prepared for this. // tbh consumer wallets dont usually work with such big txs, so probably we dont need it - let txdatas = await BlueElectrum.multiGetTransactionByTxid(['484a11c5e086a281413b9192b4f60c06abf745f08c2c28c4b4daefe6df3b9e5c']); - assert.ok(txdatas['484a11c5e086a281413b9192b4f60c06abf745f08c2c28c4b4daefe6df3b9e5c']); + const txdatas = await BlueElectrum.multiGetTransactionByTxid([ + "484a11c5e086a281413b9192b4f60c06abf745f08c2c28c4b4daefe6df3b9e5c" + ]); + assert.ok( + txdatas[ + "484a11c5e086a281413b9192b4f60c06abf745f08c2c28c4b4daefe6df3b9e5c" + ] + ); }); - it('ElectrumClient can do multiGetHistoryByAddress() to obtain txhex', async () => { - let txdatas = await BlueElectrum.multiGetTransactionByTxid( - ['881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e'], + it("ElectrumClient can do multiGetHistoryByAddress() to obtain txhex", async () => { + const txdatas = await BlueElectrum.multiGetTransactionByTxid( + ["881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e"], 3, - false, + false ); assert.strictEqual( - txdatas['881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e'], - '02000000000102f1155666b534f7cb476a0523a45dc8731d38d56b5b08e877c968812423fbd7f3010000000000000000d8a2882a692ee759b43e6af48ac152dd3410cc4b7d25031e83b3396c16ffbc8900000000000000000002400d03000000000017a914e286d58e53f9247a4710e51232cce0686f16873c870695010000000000160014d3e2ecbf4d91321794e0297e0284c47527cf878b02483045022100d18dc865fb4d087004d021d480b983b8afb177a1934ce4cd11cf97b03e17944f02206d7310687a84aab5d4696d535bca69c2db4449b48feb55fff028aa004f2d1744012103af4b208608c75f38e78f6e5abfbcad9c360fb60d3e035193b2cd0cdc8fc0155c0247304402207556e859845df41d897fe442f59b6106c8fa39c74ba5b7b8e3268ab0aebf186f0220048a9f3742339c44a1e5c78b491822b96070bcfda3f64db9dc6434f8e8068475012102456e5223ed3884dc6b0e152067fd836e3eb1485422eda45558bf83f59c6ad09f00000000', + txdatas[ + "881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e" + ], + "02000000000102f1155666b534f7cb476a0523a45dc8731d38d56b5b08e877c968812423fbd7f3010000000000000000d8a2882a692ee759b43e6af48ac152dd3410cc4b7d25031e83b3396c16ffbc8900000000000000000002400d03000000000017a914e286d58e53f9247a4710e51232cce0686f16873c870695010000000000160014d3e2ecbf4d91321794e0297e0284c47527cf878b02483045022100d18dc865fb4d087004d021d480b983b8afb177a1934ce4cd11cf97b03e17944f02206d7310687a84aab5d4696d535bca69c2db4449b48feb55fff028aa004f2d1744012103af4b208608c75f38e78f6e5abfbcad9c360fb60d3e035193b2cd0cdc8fc0155c0247304402207556e859845df41d897fe442f59b6106c8fa39c74ba5b7b8e3268ab0aebf186f0220048a9f3742339c44a1e5c78b491822b96070bcfda3f64db9dc6434f8e8068475012102456e5223ed3884dc6b0e152067fd836e3eb1485422eda45558bf83f59c6ad09f00000000" ); }); }); diff --git a/tests/integration/HDWallet.test.js b/tests/integration/HDWallet.test.js index 6de2c02a04c..cde910440b0 100644 --- a/tests/integration/HDWallet.test.js +++ b/tests/integration/HDWallet.test.js @@ -1,11 +1,19 @@ /* global it, jasmine, afterAll, beforeAll */ -import { SegwitP2SHWallet, SegwitBech32Wallet, HDSegwitP2SHWallet, HDLegacyBreadwalletWallet, HDLegacyP2PKHWallet } from '../../class'; -import { BitcoinUnit } from '../../models/bitcoinUnits'; -const bitcoin = require('bitcoinjs-lib'); -global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment -let assert = require('assert'); -global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js -let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP +import { + SegwitP2SHWallet, + SegwitBech32Wallet, + HDSegwitP2SHWallet, + HDLegacyBreadwalletWallet, + HDLegacyP2PKHWallet +} from "../../class"; +import { BitcoinUnit } from "../../models/bitcoinUnits"; + +const bitcoin = require("bitcoinjs-lib"); +global.crypto = require("crypto"); // shall be used by tests under nodejs CLI, but not in RN environment +const assert = require("assert"); +global.net = require("net"); // needed by Electrum client. For RN it is proviced in shim.js +const BlueElectrum = require("../../BlueElectrum"); +// so it connects ASAP jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; afterAll(() => { @@ -20,33 +28,50 @@ beforeAll(async () => { try { await BlueElectrum.waitTillConnected(); } catch (Err) { - console.log('failed to connect to Electrum:', Err); + console.log("failed to connect to Electrum:", Err); process.exit(2); } }); -it('can convert witness to address', () => { - let address = SegwitP2SHWallet.witnessToAddress('035c618df829af694cb99e664ce1b34f80ad2c3b49bcd0d9c0b1836c66b2d25fd8'); - assert.strictEqual(address, '34ZVGb3gT8xMLT6fpqC6dNVqJtJmvdjbD7'); +it("can convert witness to address", () => { + let address = SegwitP2SHWallet.witnessToAddress( + "035c618df829af694cb99e664ce1b34f80ad2c3b49bcd0d9c0b1836c66b2d25fd8" + ); + assert.strictEqual(address, "34ZVGb3gT8xMLT6fpqC6dNVqJtJmvdjbD7"); - address = SegwitP2SHWallet.scriptPubKeyToAddress('a914e286d58e53f9247a4710e51232cce0686f16873c87'); - assert.strictEqual(address, '3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC'); + address = SegwitP2SHWallet.scriptPubKeyToAddress( + "a914e286d58e53f9247a4710e51232cce0686f16873c87" + ); + assert.strictEqual(address, "3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC"); - address = SegwitBech32Wallet.witnessToAddress('035c618df829af694cb99e664ce1b34f80ad2c3b49bcd0d9c0b1836c66b2d25fd8'); - assert.strictEqual(address, 'bc1quhnve8q4tk3unhmjts7ymxv8cd6w9xv8wy29uv'); + address = SegwitBech32Wallet.witnessToAddress( + "035c618df829af694cb99e664ce1b34f80ad2c3b49bcd0d9c0b1836c66b2d25fd8" + ); + assert.strictEqual(address, "bc1quhnve8q4tk3unhmjts7ymxv8cd6w9xv8wy29uv"); - address = SegwitBech32Wallet.scriptPubKeyToAddress('00144d757460da5fcaf84cc22f3847faaa1078e84f6a'); - assert.strictEqual(address, 'bc1qf46hgcx6tl90snxz9uuy0742zpuwsnm27ysdh7'); + address = SegwitBech32Wallet.scriptPubKeyToAddress( + "00144d757460da5fcaf84cc22f3847faaa1078e84f6a" + ); + assert.strictEqual(address, "bc1qf46hgcx6tl90snxz9uuy0742zpuwsnm27ysdh7"); }); -it('can create a Segwit HD (BIP49)', async function() { - let mnemonic = - 'honey risk juice trip orient galaxy win situate shoot anchor bounce remind horse traffic exotic since escape mimic ramp skin judge owner topple erode'; - let hd = new HDSegwitP2SHWallet(); +it("can create a Segwit HD (BIP49)", async function() { + const mnemonic = + "honey risk juice trip orient galaxy win situate shoot anchor bounce remind horse traffic exotic since escape mimic ramp skin judge owner topple erode"; + const hd = new HDSegwitP2SHWallet(); hd.setSecret(mnemonic); - assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', hd._getExternalAddressByIndex(0)); - assert.strictEqual('35p5LwCAE7mH2css7onyQ1VuS1jgWtQ4U3', hd._getExternalAddressByIndex(1)); - assert.strictEqual('32yn5CdevZQLk3ckuZuA8fEKBco8mEkLei', hd._getInternalAddressByIndex(0)); + assert.strictEqual( + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK", + hd._getExternalAddressByIndex(0) + ); + assert.strictEqual( + "35p5LwCAE7mH2css7onyQ1VuS1jgWtQ4U3", + hd._getExternalAddressByIndex(1) + ); + assert.strictEqual( + "32yn5CdevZQLk3ckuZuA8fEKBco8mEkLei", + hd._getInternalAddressByIndex(0) + ); assert.strictEqual(true, hd.validateMnemonic()); await hd.fetchBalance(); @@ -57,23 +82,33 @@ it('can create a Segwit HD (BIP49)', async function() { assert.ok(hd._lastTxFetch > 0); assert.strictEqual(hd.transactions.length, 4); - assert.strictEqual('L4MqtwJm6hkbACLG4ho5DF8GhcXdLEbbvpJnbzA9abfD6RDpbr2m', hd._getExternalWIFByIndex(0)); assert.strictEqual( - 'ypub6WhHmKBmHNjcrUVNCa3sXduH9yxutMipDcwiKW31vWjcMbfhQHjXdyx4rqXbEtVgzdbhFJ5mZJWmfWwnP4Vjzx97admTUYKQt6b9D7jjSCp', - hd.getXpub(), + "L4MqtwJm6hkbACLG4ho5DF8GhcXdLEbbvpJnbzA9abfD6RDpbr2m", + hd._getExternalWIFByIndex(0) + ); + assert.strictEqual( + "ypub6WhHmKBmHNjcrUVNCa3sXduH9yxutMipDcwiKW31vWjcMbfhQHjXdyx4rqXbEtVgzdbhFJ5mZJWmfWwnP4Vjzx97admTUYKQt6b9D7jjSCp", + hd.getXpub() ); // checking that internal pointer and async address getter return the same address - let freeAddress = await hd.getAddressAsync(); - assert.strictEqual(hd._getExternalAddressByIndex(hd.next_free_address_index), freeAddress); - let freeChangeAddress = await hd.getChangeAddressAsync(); - assert.strictEqual(hd._getInternalAddressByIndex(hd.next_free_change_address_index), freeChangeAddress); + const freeAddress = await hd.getAddressAsync(); + assert.strictEqual( + hd._getExternalAddressByIndex(hd.next_free_address_index), + freeAddress + ); + const freeChangeAddress = await hd.getChangeAddressAsync(); + assert.strictEqual( + hd._getInternalAddressByIndex(hd.next_free_change_address_index), + freeChangeAddress + ); }); -it('HD (BIP49) can work with a gap', async function() { +it("HD (BIP49) can work with a gap", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; - let hd = new HDSegwitP2SHWallet(); - hd._xpub = 'ypub6XRzrn3HB1tjhhvrHbk1vnXCecZEdXohGzCk3GXwwbDoJ3VBzZ34jNGWbC6WrS7idXrYjjXEzcPDX5VqnHEnuNf5VAXgLfSaytMkJ2rwVqy'; // has gap + const hd = new HDSegwitP2SHWallet(); + hd._xpub = + "ypub6XRzrn3HB1tjhhvrHbk1vnXCecZEdXohGzCk3GXwwbDoJ3VBzZ34jNGWbC6WrS7idXrYjjXEzcPDX5VqnHEnuNf5VAXgLfSaytMkJ2rwVqy"; // has gap await hd.fetchBalance(); // for (let c = 0; c < 5; c++) { @@ -87,19 +122,21 @@ it('HD (BIP49) can work with a gap', async function() { assert.ok(hd.transactions.length >= 3); }); -it('Segwit HD (BIP49) can batch fetch many txs', async function() { +it("Segwit HD (BIP49) can batch fetch many txs", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; - let hd = new HDSegwitP2SHWallet(); - hd._xpub = 'ypub6WZ2c7YJ1SQ1rBYftwMqwV9bBmybXzETFxWmkzMz25bCf6FkDdXjNgR7zRW8JGSnoddNdUH7ZQS7JeQAddxdGpwgPskcsXFcvSn1JdGVcPQ'; + const hd = new HDSegwitP2SHWallet(); + hd._xpub = + "ypub6WZ2c7YJ1SQ1rBYftwMqwV9bBmybXzETFxWmkzMz25bCf6FkDdXjNgR7zRW8JGSnoddNdUH7ZQS7JeQAddxdGpwgPskcsXFcvSn1JdGVcPQ"; await hd.fetchBalance(); await hd.fetchTransactions(); assert.ok(hd.getTransactions().length === 153); }); -it('Segwit HD (BIP49) can fetch more data if pointers to last_used_addr are lagging behind', async function() { +it("Segwit HD (BIP49) can fetch more data if pointers to last_used_addr are lagging behind", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; - let hd = new HDSegwitP2SHWallet(); - hd._xpub = 'ypub6WZ2c7YJ1SQ1rBYftwMqwV9bBmybXzETFxWmkzMz25bCf6FkDdXjNgR7zRW8JGSnoddNdUH7ZQS7JeQAddxdGpwgPskcsXFcvSn1JdGVcPQ'; + const hd = new HDSegwitP2SHWallet(); + hd._xpub = + "ypub6WZ2c7YJ1SQ1rBYftwMqwV9bBmybXzETFxWmkzMz25bCf6FkDdXjNgR7zRW8JGSnoddNdUH7ZQS7JeQAddxdGpwgPskcsXFcvSn1JdGVcPQ"; hd.next_free_change_address_index = 40; hd.next_free_address_index = 50; await hd.fetchBalance(); @@ -107,137 +144,182 @@ it('Segwit HD (BIP49) can fetch more data if pointers to last_used_addr are lagg assert.strictEqual(hd.getTransactions().length, 153); }); -it('Segwit HD (BIP49) can generate addressess only via ypub', function() { - let ypub = 'ypub6WhHmKBmHNjcrUVNCa3sXduH9yxutMipDcwiKW31vWjcMbfhQHjXdyx4rqXbEtVgzdbhFJ5mZJWmfWwnP4Vjzx97admTUYKQt6b9D7jjSCp'; - let hd = new HDSegwitP2SHWallet(); +it("Segwit HD (BIP49) can generate addressess only via ypub", function() { + const ypub = + "ypub6WhHmKBmHNjcrUVNCa3sXduH9yxutMipDcwiKW31vWjcMbfhQHjXdyx4rqXbEtVgzdbhFJ5mZJWmfWwnP4Vjzx97admTUYKQt6b9D7jjSCp"; + const hd = new HDSegwitP2SHWallet(); hd._xpub = ypub; - assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', hd._getExternalAddressByIndex(0)); - assert.strictEqual('35p5LwCAE7mH2css7onyQ1VuS1jgWtQ4U3', hd._getExternalAddressByIndex(1)); - assert.strictEqual('32yn5CdevZQLk3ckuZuA8fEKBco8mEkLei', hd._getInternalAddressByIndex(0)); + assert.strictEqual( + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK", + hd._getExternalAddressByIndex(0) + ); + assert.strictEqual( + "35p5LwCAE7mH2css7onyQ1VuS1jgWtQ4U3", + hd._getExternalAddressByIndex(1) + ); + assert.strictEqual( + "32yn5CdevZQLk3ckuZuA8fEKBco8mEkLei", + hd._getInternalAddressByIndex(0) + ); }); -it('can generate Segwit HD (BIP49)', async () => { - let hd = new HDSegwitP2SHWallet(); - let hashmap = {}; +it("can generate Segwit HD (BIP49)", async () => { + const hd = new HDSegwitP2SHWallet(); + const hashmap = {}; for (let c = 0; c < 1000; c++) { await hd.generate(); - let secret = hd.getSecret(); + const secret = hd.getSecret(); if (hashmap[secret]) { - throw new Error('Duplicate secret generated!'); + throw new Error("Duplicate secret generated!"); } hashmap[secret] = 1; - assert.ok(secret.split(' ').length === 12 || secret.split(' ').length === 24); + assert.ok( + secret.split(" ").length === 12 || secret.split(" ").length === 24 + ); } - let hd2 = new HDSegwitP2SHWallet(); + const hd2 = new HDSegwitP2SHWallet(); hd2.setSecret(hd.getSecret()); assert.ok(hd2.validateMnemonic()); }); -it('HD (BIP49) can create TX', async () => { +it("HD (BIP49) can create TX", async () => { if (!process.env.HD_MNEMONIC_BIP49) { - console.error('process.env.HD_MNEMONIC_BIP49 not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP49 not set, skipped"); return; } - let hd = new HDSegwitP2SHWallet(); + const hd = new HDSegwitP2SHWallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP49); assert.ok(hd.validateMnemonic()); await hd.fetchUtxo(); await hd.getChangeAddressAsync(); // to refresh internal pointer to next free address await hd.getAddressAsync(); // to refresh internal pointer to next free address - let txhex = hd.createTx(hd.utxo, 0.000014, 0.000001, '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK'); + let txhex = hd.createTx( + hd.utxo, + 0.000014, + 0.000001, + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK" + ); assert.strictEqual( txhex, - '0100000000010187c9acd9d5714845343b18abaa26cb83299be2487c22da9c0e270f241b4d9cfe0000000017160014a239b6a0cbc7aadc2e77643de36306a6167fad15ffffffff02780500000000000017a914a3a65daca3064280ae072b9d6773c027b30abace87b45f00000000000017a9140acff2c37ed45110baece4bb9d4dcc0c6309dbbd8702483045022100f489dfbd372b66348a25f6e9ba1b5eb88a3646efcd75ef1211c96cf46eed692c0220416ac99a94c5f4a076588291d9857fc5b854e02404d69635dc35e82fde3ecd9701210202ac3bd159e54dc31e65842ad5f9a10b4eb024e83864a319b27de65ee08b2a3900000000', + "0100000000010187c9acd9d5714845343b18abaa26cb83299be2487c22da9c0e270f241b4d9cfe0000000017160014a239b6a0cbc7aadc2e77643de36306a6167fad15ffffffff02780500000000000017a914a3a65daca3064280ae072b9d6773c027b30abace87b45f00000000000017a9140acff2c37ed45110baece4bb9d4dcc0c6309dbbd8702483045022100f489dfbd372b66348a25f6e9ba1b5eb88a3646efcd75ef1211c96cf46eed692c0220416ac99a94c5f4a076588291d9857fc5b854e02404d69635dc35e82fde3ecd9701210202ac3bd159e54dc31e65842ad5f9a10b4eb024e83864a319b27de65ee08b2a3900000000" ); - txhex = hd.createTx(hd.utxo, 0.000005, 0.000001, '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK'); - var tx = bitcoin.Transaction.fromHex(txhex); + txhex = hd.createTx( + hd.utxo, + 0.000005, + 0.000001, + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK" + ); + let tx = bitcoin.Transaction.fromHex(txhex); assert.strictEqual(tx.ins.length, 1); assert.strictEqual(tx.outs.length, 2); assert.strictEqual(tx.outs[0].value, 500); assert.strictEqual(tx.outs[1].value, 25400); let toAddress = bitcoin.address.fromOutputScript(tx.outs[0].script); - let changeAddress = bitcoin.address.fromOutputScript(tx.outs[1].script); - assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', toAddress); - assert.strictEqual(hd._getInternalAddressByIndex(hd.next_free_change_address_index), changeAddress); + const changeAddress = bitcoin.address.fromOutputScript(tx.outs[1].script); + assert.strictEqual("3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK", toAddress); + assert.strictEqual( + hd._getInternalAddressByIndex(hd.next_free_change_address_index), + changeAddress + ); // - txhex = hd.createTx(hd.utxo, 0.000015, 0.000001, '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK'); + txhex = hd.createTx( + hd.utxo, + 0.000015, + 0.000001, + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK" + ); tx = bitcoin.Transaction.fromHex(txhex); assert.strictEqual(tx.ins.length, 1); assert.strictEqual(tx.outs.length, 2); // - txhex = hd.createTx(hd.utxo, 0.00025, 0.00001, '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK'); + txhex = hd.createTx( + hd.utxo, + 0.00025, + 0.00001, + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK" + ); tx = bitcoin.Transaction.fromHex(txhex); assert.strictEqual(tx.ins.length, 1); assert.strictEqual(tx.outs.length, 1); toAddress = bitcoin.address.fromOutputScript(tx.outs[0].script); - assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', toAddress); + assert.strictEqual("3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK", toAddress); // testing sendMAX hd.utxo = [ { - txid: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + txid: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", vout: 0, amount: 26000, - address: '39SpCj47M88ajRBTbkfaKRgpaX7FTLQJz5', - wif: 'L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr', + address: "39SpCj47M88ajRBTbkfaKRgpaX7FTLQJz5", + wif: "L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr" }, { - txid: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + txid: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", vout: 0, amount: 26000, - address: '39SpCj47M88ajRBTbkfaKRgpaX7FTLQJz5', - wif: 'L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr', + address: "39SpCj47M88ajRBTbkfaKRgpaX7FTLQJz5", + wif: "L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr" }, { - txid: 'cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + txid: "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", vout: 0, amount: 26000, - address: '39SpCj47M88ajRBTbkfaKRgpaX7FTLQJz5', - wif: 'L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr', - }, + address: "39SpCj47M88ajRBTbkfaKRgpaX7FTLQJz5", + wif: "L3fg5Jb6tJDVMvoG2boP4u3CxjX1Er3e7Z4zDALQdGgVLLE8zVUr" + } ]; - txhex = hd.createTx(hd.utxo, BitcoinUnit.MAX, 0.00003, '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK'); + txhex = hd.createTx( + hd.utxo, + BitcoinUnit.MAX, + 0.00003, + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK" + ); tx = bitcoin.Transaction.fromHex(txhex); assert.strictEqual(tx.outs.length, 1); assert.strictEqual(tx.outs[0].value, 75000); }); -it('Segwit HD (BIP49) can fetch UTXO', async function() { - let hd = new HDSegwitP2SHWallet(); - hd.usedAddresses = ['1Ez69SnzzmePmZX3WpEzMKTrcBF2gpNQ55', '1BiTCHeYzJNMxBLFCMkwYXNdFEdPJP53ZV']; // hacking internals +it("Segwit HD (BIP49) can fetch UTXO", async function() { + const hd = new HDSegwitP2SHWallet(); + hd.usedAddresses = [ + "1Ez69SnzzmePmZX3WpEzMKTrcBF2gpNQ55", + "1BiTCHeYzJNMxBLFCMkwYXNdFEdPJP53ZV" + ]; // hacking internals await hd.fetchUtxo(); assert.ok(hd.utxo.length >= 12); - assert.ok(typeof hd.utxo[0].confirmations === 'number'); + assert.ok(typeof hd.utxo[0].confirmations === "number"); assert.ok(hd.utxo[0].txid); assert.ok(hd.utxo[0].vout); assert.ok(hd.utxo[0].amount); assert.ok( hd.utxo[0].address && - (hd.utxo[0].address === '1Ez69SnzzmePmZX3WpEzMKTrcBF2gpNQ55' || hd.utxo[0].address === '1BiTCHeYzJNMxBLFCMkwYXNdFEdPJP53ZV'), + (hd.utxo[0].address === "1Ez69SnzzmePmZX3WpEzMKTrcBF2gpNQ55" || + hd.utxo[0].address === "1BiTCHeYzJNMxBLFCMkwYXNdFEdPJP53ZV") ); }); -it('Segwit HD (BIP49) can fetch balance with many used addresses in hierarchy', async function() { +it("Segwit HD (BIP49) can fetch balance with many used addresses in hierarchy", async function() { if (!process.env.HD_MNEMONIC_BIP49_MANY_TX) { - console.error('process.env.HD_MNEMONIC_BIP49_MANY_TX not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP49_MANY_TX not set, skipped"); return; } - let hd = new HDSegwitP2SHWallet(); + const hd = new HDSegwitP2SHWallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP49_MANY_TX); assert.ok(hd.validateMnemonic()); - let start = +new Date(); + const start = +new Date(); await hd.fetchBalance(); - let end = +new Date(); + const end = +new Date(); const took = (end - start) / 1000; - took > 15 && console.warn('took', took, "sec to fetch huge HD wallet's balance"); + took > 15 && + console.warn("took", took, "sec to fetch huge HD wallet's balance"); assert.strictEqual(hd.getBalance(), 51432); await hd.fetchUtxo(); @@ -250,15 +332,15 @@ it('Segwit HD (BIP49) can fetch balance with many used addresses in hierarchy', assert.strictEqual(hd.getTransactions().length, 107); }); -it('can work with malformed mnemonic', () => { +it("can work with malformed mnemonic", () => { let mnemonic = - 'honey risk juice trip orient galaxy win situate shoot anchor bounce remind horse traffic exotic since escape mimic ramp skin judge owner topple erode'; + "honey risk juice trip orient galaxy win situate shoot anchor bounce remind horse traffic exotic since escape mimic ramp skin judge owner topple erode"; let hd = new HDSegwitP2SHWallet(); hd.setSecret(mnemonic); - let seed1 = hd.getMnemonicToSeedHex(); + const seed1 = hd.getMnemonicToSeedHex(); assert.ok(hd.validateMnemonic()); - mnemonic = 'hell'; + mnemonic = "hell"; hd = new HDSegwitP2SHWallet(); hd.setSecret(mnemonic); assert.ok(!hd.validateMnemonic()); @@ -266,37 +348,61 @@ it('can work with malformed mnemonic', () => { // now, malformed mnemonic mnemonic = - ' honey risk juice trip orient galaxy win !situate ;; shoot ;;; anchor Bounce remind\nhorse \n traffic exotic since escape mimic ramp skin judge owner topple erode '; + " honey risk juice trip orient galaxy win !situate ;; shoot ;;; anchor Bounce remind\nhorse \n traffic exotic since escape mimic ramp skin judge owner topple erode "; hd = new HDSegwitP2SHWallet(); hd.setSecret(mnemonic); - let seed2 = hd.getMnemonicToSeedHex(); + const seed2 = hd.getMnemonicToSeedHex(); assert.strictEqual(seed1, seed2); assert.ok(hd.validateMnemonic()); }); -it('can create a Legacy HD (BIP44)', async function() { +it("can create a Legacy HD (BIP44)", async function() { if (!process.env.HD_MNEMONIC_BREAD) { - console.error('process.env.HD_MNEMONIC_BREAD not set, skipped'); + console.error("process.env.HD_MNEMONIC_BREAD not set, skipped"); return; } - let mnemonic = process.env.HD_MNEMONIC_BREAD; - let hd = new HDLegacyP2PKHWallet(); + const mnemonic = process.env.HD_MNEMONIC_BREAD; + const hd = new HDLegacyP2PKHWallet(); hd.setSecret(mnemonic); assert.strictEqual(hd.validateMnemonic(), true); - assert.strictEqual(hd._getExternalAddressByIndex(0), '12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG'); - assert.strictEqual(hd._getExternalAddressByIndex(1), '1QDCFcpnrZ4yrAQxmbvSgeUC9iZZ8ehcR5'); - assert.strictEqual(hd._getInternalAddressByIndex(0), '1KZjqYHm7a1DjhjcdcjfQvYfF2h6PqatjX'); - assert.strictEqual(hd._getInternalAddressByIndex(1), '13CW9WWBsWpDUvLtbFqYziWBWTYUoQb4nU'); + assert.strictEqual( + hd._getExternalAddressByIndex(0), + "12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG" + ); + assert.strictEqual( + hd._getExternalAddressByIndex(1), + "1QDCFcpnrZ4yrAQxmbvSgeUC9iZZ8ehcR5" + ); + assert.strictEqual( + hd._getInternalAddressByIndex(0), + "1KZjqYHm7a1DjhjcdcjfQvYfF2h6PqatjX" + ); + assert.strictEqual( + hd._getInternalAddressByIndex(1), + "13CW9WWBsWpDUvLtbFqYziWBWTYUoQb4nU" + ); assert.strictEqual( hd.getXpub(), - 'xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps', + "xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps" ); - assert.strictEqual(hd._getExternalWIFByIndex(0), 'L1hqNoJ26YuCdujMBJfWBNfgf4Jo7AcKFvcNcKLoMtoJDdDtRq7Q'); - assert.strictEqual(hd._getExternalWIFByIndex(1), 'KyyH4h59iatJWwFfiYPnYkw39SP7cBwydC3xzszsBBXHpfwz9cKb'); - assert.strictEqual(hd._getInternalWIFByIndex(0), 'Kx3QkrfemEEV49Mj5oWfb4bsWymboPdstta7eN3kAzop9apxYEFP'); - assert.strictEqual(hd._getInternalWIFByIndex(1), 'Kwfg1EDjFapN9hgwafdNPEH22z3vkd4gtG785vXXjJ6uvVWAJGtr'); + assert.strictEqual( + hd._getExternalWIFByIndex(0), + "L1hqNoJ26YuCdujMBJfWBNfgf4Jo7AcKFvcNcKLoMtoJDdDtRq7Q" + ); + assert.strictEqual( + hd._getExternalWIFByIndex(1), + "KyyH4h59iatJWwFfiYPnYkw39SP7cBwydC3xzszsBBXHpfwz9cKb" + ); + assert.strictEqual( + hd._getInternalWIFByIndex(0), + "Kx3QkrfemEEV49Mj5oWfb4bsWymboPdstta7eN3kAzop9apxYEFP" + ); + assert.strictEqual( + hd._getInternalWIFByIndex(1), + "Kwfg1EDjFapN9hgwafdNPEH22z3vkd4gtG785vXXjJ6uvVWAJGtr" + ); await hd.fetchBalance(); assert.strictEqual(hd.balance, 0); assert.ok(hd._lastTxFetch === 0); @@ -306,95 +412,139 @@ it('can create a Legacy HD (BIP44)', async function() { assert.strictEqual(hd.next_free_address_index, 1); assert.strictEqual(hd.next_free_change_address_index, 1); - for (let tx of hd.getTransactions()) { - assert.ok(tx.value === 1000 || tx.value === 1377 || tx.value === -1377 || tx.value === -1000); + for (const tx of hd.getTransactions()) { + assert.ok( + tx.value === 1000 || + tx.value === 1377 || + tx.value === -1377 || + tx.value === -1000 + ); } // checking that internal pointer and async address getter return the same address - let freeAddress = await hd.getAddressAsync(); - assert.strictEqual(hd._getExternalAddressByIndex(hd.next_free_address_index), freeAddress); + const freeAddress = await hd.getAddressAsync(); + assert.strictEqual( + hd._getExternalAddressByIndex(hd.next_free_address_index), + freeAddress + ); }); -it('Legacy HD (BIP44) can generate addressess based on xpub', async function() { - let xpub = 'xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps'; - let hd = new HDLegacyP2PKHWallet(); +it("Legacy HD (BIP44) can generate addressess based on xpub", async function() { + const xpub = + "xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps"; + const hd = new HDLegacyP2PKHWallet(); hd._xpub = xpub; - assert.strictEqual(hd._getExternalAddressByIndex(0), '12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG'); - assert.strictEqual(hd._getInternalAddressByIndex(0), '1KZjqYHm7a1DjhjcdcjfQvYfF2h6PqatjX'); - assert.strictEqual(hd._getExternalAddressByIndex(1), '1QDCFcpnrZ4yrAQxmbvSgeUC9iZZ8ehcR5'); - assert.strictEqual(hd._getInternalAddressByIndex(1), '13CW9WWBsWpDUvLtbFqYziWBWTYUoQb4nU'); + assert.strictEqual( + hd._getExternalAddressByIndex(0), + "12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG" + ); + assert.strictEqual( + hd._getInternalAddressByIndex(0), + "1KZjqYHm7a1DjhjcdcjfQvYfF2h6PqatjX" + ); + assert.strictEqual( + hd._getExternalAddressByIndex(1), + "1QDCFcpnrZ4yrAQxmbvSgeUC9iZZ8ehcR5" + ); + assert.strictEqual( + hd._getInternalAddressByIndex(1), + "13CW9WWBsWpDUvLtbFqYziWBWTYUoQb4nU" + ); }); -it('Legacy HD (BIP44) can create TX', async () => { +it("Legacy HD (BIP44) can create TX", async () => { if (!process.env.HD_MNEMONIC) { - console.error('process.env.HD_MNEMONIC not set, skipped'); + console.error("process.env.HD_MNEMONIC not set, skipped"); return; } - let hd = new HDLegacyP2PKHWallet(); + const hd = new HDLegacyP2PKHWallet(); hd.setSecret(process.env.HD_MNEMONIC); assert.ok(hd.validateMnemonic()); await hd.fetchUtxo(); await hd.getChangeAddressAsync(); // to refresh internal pointer to next free address await hd.getAddressAsync(); // to refresh internal pointer to next free address - let txhex = hd.createTx(hd.utxo, 0.0008, 0.000005, '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK'); + let txhex = hd.createTx( + hd.utxo, + 0.0008, + 0.000005, + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK" + ); assert.strictEqual( txhex, - '01000000045fbc74110c2d6fcf4d1161a59913fbcd2b6ab3c5a9eb4d0dc0859515cbc8654f030000006b4830450221009be5dbe37db5a8409ddce3570140c95d162a07651b1e48cf39a6a741892adc53022061a25b8024d8f3cb1b94f264245de0c6e9a103ea557ddeb66245b40ec8e9384b012102ad7b2216f3a2b38d56db8a7ee5c540fd12c4bbb7013106eff78cc2ace65aa002ffffffff5fbc74110c2d6fcf4d1161a59913fbcd2b6ab3c5a9eb4d0dc0859515cbc8654f000000006a47304402207106e9fa4e2e35d351fbccc9c0fad3356d85d0cd35a9d7e9cbcefce5440da1e5022073c1905b5927447378c0f660e62900c1d4b2691730799458889fb87d86f5159101210316e84a2556f30a199541633f5dda6787710ccab26771b7084f4c9e1104f47667ffffffff5fbc74110c2d6fcf4d1161a59913fbcd2b6ab3c5a9eb4d0dc0859515cbc8654f020000006a4730440220250b15094096c4d4fe6793da8e45fa118ed057cc2759a480c115e76e23590791022079cdbdc9e630d713395602071e2837ecc1d192a36a24d8ec71bc51d5e62b203b01210316e84a2556f30a199541633f5dda6787710ccab26771b7084f4c9e1104f47667ffffffff5fbc74110c2d6fcf4d1161a59913fbcd2b6ab3c5a9eb4d0dc0859515cbc8654f010000006b483045022100879da610e6ed12c84d55f12baf3bf6222d59b5282502b3c7f4db1d22152c16900220759a1c88583cbdaf7fde21c273ad985dfdf94a2fa85e42ee41dcea2fd69136fd012102ad7b2216f3a2b38d56db8a7ee5c540fd12c4bbb7013106eff78cc2ace65aa002ffffffff02803801000000000017a914a3a65daca3064280ae072b9d6773c027b30abace872c4c0000000000001976a9146ee5e3e66dc73587a3a2d77a1a6c8554fae21b8a88ac00000000', + "01000000045fbc74110c2d6fcf4d1161a59913fbcd2b6ab3c5a9eb4d0dc0859515cbc8654f030000006b4830450221009be5dbe37db5a8409ddce3570140c95d162a07651b1e48cf39a6a741892adc53022061a25b8024d8f3cb1b94f264245de0c6e9a103ea557ddeb66245b40ec8e9384b012102ad7b2216f3a2b38d56db8a7ee5c540fd12c4bbb7013106eff78cc2ace65aa002ffffffff5fbc74110c2d6fcf4d1161a59913fbcd2b6ab3c5a9eb4d0dc0859515cbc8654f000000006a47304402207106e9fa4e2e35d351fbccc9c0fad3356d85d0cd35a9d7e9cbcefce5440da1e5022073c1905b5927447378c0f660e62900c1d4b2691730799458889fb87d86f5159101210316e84a2556f30a199541633f5dda6787710ccab26771b7084f4c9e1104f47667ffffffff5fbc74110c2d6fcf4d1161a59913fbcd2b6ab3c5a9eb4d0dc0859515cbc8654f020000006a4730440220250b15094096c4d4fe6793da8e45fa118ed057cc2759a480c115e76e23590791022079cdbdc9e630d713395602071e2837ecc1d192a36a24d8ec71bc51d5e62b203b01210316e84a2556f30a199541633f5dda6787710ccab26771b7084f4c9e1104f47667ffffffff5fbc74110c2d6fcf4d1161a59913fbcd2b6ab3c5a9eb4d0dc0859515cbc8654f010000006b483045022100879da610e6ed12c84d55f12baf3bf6222d59b5282502b3c7f4db1d22152c16900220759a1c88583cbdaf7fde21c273ad985dfdf94a2fa85e42ee41dcea2fd69136fd012102ad7b2216f3a2b38d56db8a7ee5c540fd12c4bbb7013106eff78cc2ace65aa002ffffffff02803801000000000017a914a3a65daca3064280ae072b9d6773c027b30abace872c4c0000000000001976a9146ee5e3e66dc73587a3a2d77a1a6c8554fae21b8a88ac00000000" ); - var tx = bitcoin.Transaction.fromHex(txhex); + let tx = bitcoin.Transaction.fromHex(txhex); assert.strictEqual(tx.ins.length, 4); assert.strictEqual(tx.outs.length, 2); assert.strictEqual(tx.outs[0].value, 80000); // payee assert.strictEqual(tx.outs[1].value, 19500); // change - let toAddress = bitcoin.address.fromOutputScript(tx.outs[0].script); - let changeAddress = bitcoin.address.fromOutputScript(tx.outs[1].script); - assert.strictEqual('3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK', toAddress); - assert.strictEqual(hd._getInternalAddressByIndex(hd.next_free_change_address_index), changeAddress); + const toAddress = bitcoin.address.fromOutputScript(tx.outs[0].script); + const changeAddress = bitcoin.address.fromOutputScript(tx.outs[1].script); + assert.strictEqual("3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK", toAddress); + assert.strictEqual( + hd._getInternalAddressByIndex(hd.next_free_change_address_index), + changeAddress + ); // checking that change amount is at least 3x of fee, otherwise screw the change, just add it to fee. // theres 0.001 on UTXOs, lets transfer (0.001 - 100sat), soo fee is equal to change (100 sat) // which throws @dust error if broadcasted - txhex = hd.createTx(hd.utxo, 0.000998, 0.000001, '3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK'); + txhex = hd.createTx( + hd.utxo, + 0.000998, + 0.000001, + "3GcKN7q7gZuZ8eHygAhHrvPa5zZbG5Q1rK" + ); tx = bitcoin.Transaction.fromHex(txhex); assert.strictEqual(tx.ins.length, 4); assert.strictEqual(tx.outs.length, 1); // only 1 output, which means change is neglected assert.strictEqual(tx.outs[0].value, 99800); }); -it('Legacy HD (BIP44) can fetch UTXO', async function() { - let hd = new HDLegacyP2PKHWallet(); - hd.usedAddresses = ['1Ez69SnzzmePmZX3WpEzMKTrcBF2gpNQ55', '1BiTCHeYzJNMxBLFCMkwYXNdFEdPJP53ZV']; // hacking internals +it("Legacy HD (BIP44) can fetch UTXO", async function() { + const hd = new HDLegacyP2PKHWallet(); + hd.usedAddresses = [ + "1Ez69SnzzmePmZX3WpEzMKTrcBF2gpNQ55", + "1BiTCHeYzJNMxBLFCMkwYXNdFEdPJP53ZV" + ]; // hacking internals await hd.fetchUtxo(); assert.ok(hd.utxo.length >= 12); - assert.ok(typeof hd.utxo[0].confirmations === 'number'); + assert.ok(typeof hd.utxo[0].confirmations === "number"); assert.ok(hd.utxo[0].txid); assert.ok(hd.utxo[0].vout); assert.ok(hd.utxo[0].amount); assert.ok( hd.utxo[0].address && - (hd.utxo[0].address === '1Ez69SnzzmePmZX3WpEzMKTrcBF2gpNQ55' || hd.utxo[0].address === '1BiTCHeYzJNMxBLFCMkwYXNdFEdPJP53ZV'), + (hd.utxo[0].address === "1Ez69SnzzmePmZX3WpEzMKTrcBF2gpNQ55" || + hd.utxo[0].address === "1BiTCHeYzJNMxBLFCMkwYXNdFEdPJP53ZV") ); }); -it('HD breadwallet works', async function() { +it("HD breadwallet works", async function() { if (!process.env.HD_MNEMONIC_BREAD) { - console.error('process.env.HD_MNEMONIC_BREAD not set, skipped'); + console.error("process.env.HD_MNEMONIC_BREAD not set, skipped"); return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; - let hdBread = new HDLegacyBreadwalletWallet(); + const hdBread = new HDLegacyBreadwalletWallet(); hdBread.setSecret(process.env.HD_MNEMONIC_BREAD); assert.strictEqual(hdBread.validateMnemonic(), true); - assert.strictEqual(hdBread._getExternalAddressByIndex(0), '1ARGkNMdsBE36fJhddSwf8PqBXG3s4d2KU'); - assert.strictEqual(hdBread._getInternalAddressByIndex(0), '1JLvA5D7RpWgChb4A5sFcLNrfxYbyZdw3V'); + assert.strictEqual( + hdBread._getExternalAddressByIndex(0), + "1ARGkNMdsBE36fJhddSwf8PqBXG3s4d2KU" + ); + assert.strictEqual( + hdBread._getInternalAddressByIndex(0), + "1JLvA5D7RpWgChb4A5sFcLNrfxYbyZdw3V" + ); assert.strictEqual( hdBread.getXpub(), - 'xpub68nLLEi3KERQY7jyznC9PQSpSjmekrEmN8324YRCXayMXaavbdEJsK4gEcX2bNf9vGzT4xRks9utZ7ot1CTHLtdyCn9udvv1NWvtY7HXroh', + "xpub68nLLEi3KERQY7jyznC9PQSpSjmekrEmN8324YRCXayMXaavbdEJsK4gEcX2bNf9vGzT4xRks9utZ7ot1CTHLtdyCn9udvv1NWvtY7HXroh" ); await hdBread.fetchBalance(); assert.strictEqual(hdBread.balance, 0); @@ -403,7 +553,7 @@ it('HD breadwallet works', async function() { await hdBread.fetchTransactions(); assert.ok(hdBread._lastTxFetch > 0); assert.strictEqual(hdBread.transactions.length, 177); - for (let tx of hdBread.getTransactions()) { + for (const tx of hdBread.getTransactions()) { assert.ok(tx.confirmations); } @@ -411,20 +561,23 @@ it('HD breadwallet works', async function() { assert.strictEqual(hdBread.next_free_change_address_index, 118); // checking that internal pointer and async address getter return the same address - let freeAddress = await hdBread.getAddressAsync(); - assert.strictEqual(hdBread._getExternalAddressByIndex(hdBread.next_free_address_index), freeAddress); + const freeAddress = await hdBread.getAddressAsync(); + assert.strictEqual( + hdBread._getExternalAddressByIndex(hdBread.next_free_address_index), + freeAddress + ); }); -it('can convert blockchain.info TX to blockcypher TX format', () => { +it("can convert blockchain.info TX to blockcypher TX format", () => { const blockchaininfotx = { - hash: '25aa409a9ecbea6a987b35cef18ffa9c53f5ba985bdaadffaac85cdf9fdbb9e1', + hash: "25aa409a9ecbea6a987b35cef18ffa9c53f5ba985bdaadffaac85cdf9fdbb9e1", ver: 1, vin_sz: 1, vout_sz: 1, size: 189, weight: 756, fee: 1184, - relayed_by: '0.0.0.0', + relayed_by: "0.0.0.0", lock_time: 0, tx_index: 357712243, double_spend: false, @@ -439,19 +592,20 @@ it('can convert blockchain.info TX to blockcypher TX format', () => { tx_index: 357704878, n: 1, spent: true, - script: '76a9147580ebb44301a1165e73e25bcccd7372e1bbfe9c88ac', + script: "76a9147580ebb44301a1165e73e25bcccd7372e1bbfe9c88ac", type: 0, - addr: '1BiJW1jyUaxcJp2JWwbPLPzB1toPNWTFJV', + addr: "1BiJW1jyUaxcJp2JWwbPLPzB1toPNWTFJV", xpub: { - m: 'xpub68nLLEi3KERQY7jyznC9PQSpSjmekrEmN8324YRCXayMXaavbdEJsK4gEcX2bNf9vGzT4xRks9utZ7ot1CTHLtdyCn9udvv1NWvtY7HXroh', - path: 'M/1/117', - }, + m: + "xpub68nLLEi3KERQY7jyznC9PQSpSjmekrEmN8324YRCXayMXaavbdEJsK4gEcX2bNf9vGzT4xRks9utZ7ot1CTHLtdyCn9udvv1NWvtY7HXroh", + path: "M/1/117" + } }, sequence: 4294967295, script: - '47304402206f676bd8c87dcf6f9e5016a8d222b06cd542d824e3b22c9ae937c05e59590f7602206cfb75a516e70a79e5f33031a189ebca55f1339be8fcd94b1e1fc9149b55354201210339b7fc52be2c33a64f8f4020c9e80fb23f5ee89992a8c5dd070309b001f16a21', - witness: '', - }, + "47304402206f676bd8c87dcf6f9e5016a8d222b06cd542d824e3b22c9ae937c05e59590f7602206cfb75a516e70a79e5f33031a189ebca55f1339be8fcd94b1e1fc9149b55354201210339b7fc52be2c33a64f8f4020c9e80fb23f5ee89992a8c5dd070309b001f16a21", + witness: "" + } ], out: [ { @@ -459,16 +613,16 @@ it('can convert blockchain.info TX to blockcypher TX format', () => { tx_index: 357712243, n: 0, spent: true, - script: 'a914e286d58e53f9247a4710e51232cce0686f16873c87', + script: "a914e286d58e53f9247a4710e51232cce0686f16873c87", type: 0, - addr: '3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC', - }, - ], + addr: "3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC" + } + ] }; - let blockcyphertx = HDSegwitP2SHWallet.convertTx(blockchaininfotx); + const blockcyphertx = HDSegwitP2SHWallet.convertTx(blockchaininfotx); assert.ok(blockcyphertx.received); // time assert.ok(blockcyphertx.hash); assert.ok(blockcyphertx.value); - assert.ok(typeof blockcyphertx.confirmations === 'number'); + assert.ok(typeof blockcyphertx.confirmations === "number"); assert.ok(blockcyphertx.outputs); }); diff --git a/tests/integration/LightningCustodianWallet.test.js b/tests/integration/LightningCustodianWallet.test.js index f3e5aee35f6..3fd018cc91b 100644 --- a/tests/integration/LightningCustodianWallet.test.js +++ b/tests/integration/LightningCustodianWallet.test.js @@ -1,17 +1,18 @@ /* global it, describe, jasmine */ -import Frisbee from 'frisbee'; -import { LightningCustodianWallet } from '../../class'; -let assert = require('assert'); +import Frisbee from "frisbee"; +import { LightningCustodianWallet } from "../../class"; -describe('LightningCustodianWallet', () => { - let l1 = new LightningCustodianWallet(); +const assert = require("assert"); - it.skip('issue credentials', async () => { +describe("LightningCustodianWallet", () => { + const l1 = new LightningCustodianWallet(); + + it.skip("issue credentials", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; assert.ok(l1.refill_addressess.length === 0); assert.ok(l1._refresh_token_created_ts === 0); assert.ok(l1._access_token_created_ts === 0); - l1.balance = 'FAKE'; + l1.balance = "FAKE"; await l1.createAccount(false); await l1.authorize(); @@ -23,12 +24,12 @@ describe('LightningCustodianWallet', () => { console.log(l1.getSecret()); }); - it('can create, auth and getbtc', async () => { + it("can create, auth and getbtc", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; assert.ok(l1.refill_addressess.length === 0); assert.ok(l1._refresh_token_created_ts === 0); assert.ok(l1._access_token_created_ts === 0); - l1.balance = 'FAKE'; + l1.balance = "FAKE"; await l1.createAccount(true); await l1.authorize(); @@ -50,10 +51,10 @@ describe('LightningCustodianWallet', () => { assert.ok(l1.transactions_raw.length === l1.getTransactions().length); }); - it('can refresh token', async () => { + it("can refresh token", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; - let oldRefreshToken = l1.refresh_token; - let oldAccessToken = l1.access_token; + const oldRefreshToken = l1.refresh_token; + const oldAccessToken = l1.access_token; await l1.refreshAcessToken(); assert.ok(oldRefreshToken !== l1.refresh_token); assert.ok(oldAccessToken !== l1.access_token); @@ -61,13 +62,13 @@ describe('LightningCustodianWallet', () => { assert.ok(l1.refresh_token); }); - it('can use existing login/pass', async () => { + it("can use existing login/pass", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; if (!process.env.BLITZHUB) { - console.error('process.env.BLITZHUB not set, skipped'); + console.error("process.env.BLITZHUB not set, skipped"); return; } - let l2 = new LightningCustodianWallet(); + const l2 = new LightningCustodianWallet(); l2.setSecret(process.env.BLITZHUB); await l2.authorize(); await l2.fetchPendingTransactions(); @@ -76,31 +77,34 @@ describe('LightningCustodianWallet', () => { assert.ok(l2.pending_transactions_raw.length === 0); assert.ok(l2.transactions_raw.length > 0); assert.ok(l2.transactions_raw.length === l2.getTransactions().length); - for (let tx of l2.getTransactions()) { - assert.ok(typeof tx.fee !== 'undefined'); + for (const tx of l2.getTransactions()) { + assert.ok(typeof tx.fee !== "undefined"); assert.ok(tx.value); assert.ok(tx.timestamp); assert.ok(tx.description || tx.memo, JSON.stringify(tx)); assert.ok(!isNaN(tx.value)); - assert.ok(tx.type === 'bitcoind_tx' || tx.type === 'paid_invoice', 'unexpected tx type ' + tx.type); + assert.ok( + tx.type === "bitcoind_tx" || tx.type === "paid_invoice", + "unexpected tx type " + tx.type + ); } await l2.fetchBalance(); assert.ok(l2.getBalance() > 0); }); - it('can decode & check invoice', async () => { + it("can decode & check invoice", async () => { if (!process.env.BLITZHUB) { - console.error('process.env.BLITZHUB not set, skipped'); + console.error("process.env.BLITZHUB not set, skipped"); return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; - let l2 = new LightningCustodianWallet(); + const l2 = new LightningCustodianWallet(); l2.setSecret(process.env.BLITZHUB); await l2.authorize(); let invoice = - 'lnbc1u1pdcqpt3pp5ltuevvq2g69kdrzcegrs9gfqjer45rwjc0w736qjl92yvwtxhn6qdp8dp6kuerjv4j9xct5daeks6tnyp3xc6t50f582cscqp2zrkghzl535xjav52ns0rpskcn20takzdr2e02wn4xqretlgdemg596acq5qtfqhjk4jpr7jk8qfuuka2k0lfwjsk9mchwhxcgxzj3tsp09gfpy'; - let decoded = await l2.decodeInvoice(invoice); + "lnbc1u1pdcqpt3pp5ltuevvq2g69kdrzcegrs9gfqjer45rwjc0w736qjl92yvwtxhn6qdp8dp6kuerjv4j9xct5daeks6tnyp3xc6t50f582cscqp2zrkghzl535xjav52ns0rpskcn20takzdr2e02wn4xqretlgdemg596acq5qtfqhjk4jpr7jk8qfuuka2k0lfwjsk9mchwhxcgxzj3tsp09gfpy"; + const decoded = await l2.decodeInvoice(invoice); assert.ok(decoded.payment_hash); assert.ok(decoded.description); @@ -109,7 +113,7 @@ describe('LightningCustodianWallet', () => { await l2.checkRouteInvoice(invoice); // checking that bad invoice cant be decoded - invoice = 'gsom'; + invoice = "gsom"; let error = false; try { await l2.decodeInvoice(invoice); @@ -119,43 +123,43 @@ describe('LightningCustodianWallet', () => { assert.ok(error); }); - it('can pay invoice', async () => { + it("can pay invoice", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; if (!process.env.BLITZHUB) { - console.error('process.env.BLITZHUB not set, skipped'); + console.error("process.env.BLITZHUB not set, skipped"); return; } if (!process.env.STRIKE) { - console.error('process.env.STRIKE not set, skipped'); + console.error("process.env.STRIKE not set, skipped"); return; } const api = new Frisbee({ - baseURI: 'https://api.strike.acinq.co', + baseURI: "https://api.strike.acinq.co" }); - api.auth(process.env.STRIKE + ':'); + api.auth(process.env.STRIKE + ":"); - const res = await api.post('/api/v1/charges', { + const res = await api.post("/api/v1/charges", { headers: { - 'Content-Type': 'application/x-www-form-urlencoded', + "Content-Type": "application/x-www-form-urlencoded" }, - body: 'amount=1¤cy=btc&description=acceptance+test', + body: "amount=1¤cy=btc&description=acceptance+test" }); if (!res.body || !res.body.payment_request) { - throw new Error('Strike problem: ' + JSON.stringify(res)); + throw new Error("Strike problem: " + JSON.stringify(res)); } - let invoice = res.body.payment_request; + const invoice = res.body.payment_request; - let l2 = new LightningCustodianWallet(); + const l2 = new LightningCustodianWallet(); l2.setSecret(process.env.BLITZHUB); await l2.authorize(); await l2.fetchTransactions(); - let txLen = l2.transactions_raw.length; + const txLen = l2.transactions_raw.length; - let decoded = await l2.decodeInvoice(invoice); + const decoded = await l2.decodeInvoice(invoice); assert.ok(decoded.payment_hash); assert.ok(decoded.description); @@ -165,14 +169,22 @@ describe('LightningCustodianWallet', () => { await l2.payInvoice(invoice); let end = +new Date(); if ((end - start) / 1000 > 9) { - console.warn('payInvoice took', (end - start) / 1000, 'sec'); + console.warn("payInvoice took", (end - start) / 1000, "sec"); } await l2.fetchTransactions(); assert.strictEqual(l2.transactions_raw.length, txLen + 1); - let lastTx = l2.transactions_raw[l2.transactions_raw.length - 1]; - assert.strictEqual(typeof lastTx.payment_preimage, 'string', 'preimage is present and is a string'); - assert.strictEqual(lastTx.payment_preimage.length, 64, 'preimage is present and is a string of 32 hex-encoded bytes'); + const lastTx = l2.transactions_raw[l2.transactions_raw.length - 1]; + assert.strictEqual( + typeof lastTx.payment_preimage, + "string", + "preimage is present and is a string" + ); + assert.strictEqual( + lastTx.payment_preimage.length, + 64, + "preimage is present and is a string of 32 hex-encoded bytes" + ); // transactions became more after paying an invoice // now, trying to pay duplicate invoice @@ -189,43 +201,43 @@ describe('LightningCustodianWallet', () => { // havent changed since last time end = +new Date(); if ((end - start) / 1000 > 9) { - console.warn('duplicate payInvoice took', (end - start) / 1000, 'sec'); + console.warn("duplicate payInvoice took", (end - start) / 1000, "sec"); } }); - it('can create invoice and pay other blitzhub invoice', async () => { + it("can create invoice and pay other blitzhub invoice", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; if (!process.env.BLITZHUB) { - console.error('process.env.BLITZHUB not set, skipped'); + console.error("process.env.BLITZHUB not set, skipped"); return; } - let lOld = new LightningCustodianWallet(); + const lOld = new LightningCustodianWallet(); lOld.setSecret(process.env.BLITZHUB); await lOld.authorize(); await lOld.fetchTransactions(); let txLen = lOld.transactions_raw.length; // creating LND wallet - let lNew = new LightningCustodianWallet(); + const lNew = new LightningCustodianWallet(); await lNew.createAccount(true); await lNew.authorize(); await lNew.fetchBalance(); assert.strictEqual(lNew.balance, 0); let invoices = await lNew.getUserInvoices(); - let invoice = await lNew.addInvoice(1, 'test memo'); + let invoice = await lNew.addInvoice(1, "test memo"); let invoices2 = await lNew.getUserInvoices(); assert.strictEqual(invoices2.length, invoices.length + 1); assert.ok(invoices2[0].ispaid === false); assert.ok(invoices2[0].description); - assert.strictEqual(invoices2[0].description, 'test memo'); + assert.strictEqual(invoices2[0].description, "test memo"); assert.ok(invoices2[0].payment_request); assert.ok(invoices2[0].timestamp); assert.ok(invoices2[0].expire_time); assert.strictEqual(invoices2[0].amt, 1); - for (let inv of invoices2) { - assert.strictEqual(inv.type, 'user_invoice'); + for (const inv of invoices2) { + assert.strictEqual(inv.type, "user_invoice"); } await lOld.fetchBalance(); @@ -233,11 +245,11 @@ describe('LightningCustodianWallet', () => { await lOld.checkRouteInvoice(invoice); - let start = +new Date(); + const start = +new Date(); await lOld.payInvoice(invoice); - let end = +new Date(); + const end = +new Date(); if ((end - start) / 1000 > 9) { - console.warn('payInvoice took', (end - start) / 1000, 'sec'); + console.warn("payInvoice took", (end - start) / 1000, "sec"); } invoices2 = await lNew.getUserInvoices(); @@ -249,18 +261,25 @@ describe('LightningCustodianWallet', () => { assert.strictEqual(lNew.balance, 1); await lOld.fetchTransactions(); - assert.strictEqual(lOld.transactions_raw.length, txLen + 1, 'internal invoice should also produce record in payer`s tx list'); - let newTx = lOld.transactions_raw.slice().pop(); - assert.ok(typeof newTx.fee !== 'undefined'); + assert.strictEqual( + lOld.transactions_raw.length, + txLen + 1, + "internal invoice should also produce record in payer`s tx list" + ); + const newTx = lOld.transactions_raw.slice().pop(); + assert.ok(typeof newTx.fee !== "undefined"); assert.ok(newTx.value); assert.ok(newTx.description || newTx.memo, JSON.stringify(newTx)); assert.ok(newTx.timestamp); assert.ok(!isNaN(newTx.value)); - assert.ok(newTx.type === 'paid_invoice', 'unexpected tx type ' + newTx.type); + assert.ok( + newTx.type === "paid_invoice", + "unexpected tx type " + newTx.type + ); // now, paying back that amount oldBalance = lOld.balance; - invoice = await lOld.addInvoice(1, 'test memo'); + invoice = await lOld.addInvoice(1, "test memo"); await lNew.payInvoice(invoice); await lOld.fetchBalance(); await lNew.fetchBalance(); @@ -272,7 +291,7 @@ describe('LightningCustodianWallet', () => { let coughtError = false; await lOld.fetchTransactions(); txLen = lOld.transactions_raw.length; - let invLen = (await lNew.getUserInvoices()).length; + const invLen = (await lNew.getUserInvoices()).length; try { await lOld.payInvoice(invoice); } catch (Err) { @@ -281,39 +300,47 @@ describe('LightningCustodianWallet', () => { assert.ok(coughtError); await lOld.fetchTransactions(); - assert.strictEqual(txLen, lOld.transactions_raw.length, 'tx count should not be changed'); - assert.strictEqual(invLen, (await lNew.getUserInvoices()).length, 'invoices count should not be changed'); + assert.strictEqual( + txLen, + lOld.transactions_raw.length, + "tx count should not be changed" + ); + assert.strictEqual( + invLen, + (await lNew.getUserInvoices()).length, + "invoices count should not be changed" + ); // testing how limiting works: assert.strictEqual(lNew.user_invoices_raw.length, 1); - await lNew.addInvoice(666, 'test memo 2'); + await lNew.addInvoice(666, "test memo 2"); invoices = await lNew.getUserInvoices(1); assert.strictEqual(invoices.length, 2); assert.strictEqual(invoices[0].amt, 1); assert.strictEqual(invoices[1].amt, 666); }); - it('can pay free amount (tip) invoice', async function() { + it("can pay free amount (tip) invoice", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; if (!process.env.BLITZHUB) { - console.error('process.env.BLITZHUB not set, skipped'); + console.error("process.env.BLITZHUB not set, skipped"); return; } // fetchig invoice from tippin.me : const api = new Frisbee({ - baseURI: 'https://tippin.me', + baseURI: "https://tippin.me" }); - const res = await api.post('/lndreq/newinvoice.php', { + const res = await api.post("/lndreq/newinvoice.php", { headers: { - Origin: 'https://tippin.me', - 'Accept-Encoding': 'gzip, deflate, br', - 'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8', - 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', - Accept: 'application/json, text/javascript, */*; q=0.01', + Origin: "https://tippin.me", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8", + "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", + Accept: "application/json, text/javascript, */*; q=0.01" }, - body: 'userid=1188&username=overtorment&istaco=0&customAmnt=0&customMemo=', + body: "userid=1188&username=overtorment&istaco=0&customAmnt=0&customMemo=" }); let json; @@ -321,22 +348,22 @@ describe('LightningCustodianWallet', () => { if (res && res.body && (json = JSON.parse(res.body)) && json.message) { invoice = json.message; } else { - throw new Error('tippin.me problem: ' + JSON.stringify(res)); + throw new Error("tippin.me problem: " + JSON.stringify(res)); } // --> use to pay specific invoice // invoice = // 'lnbc1pwrp35spp5z62nvj8yw6luq7ns4a8utpwn2qkkdwdt0ludwm54wjeazk2xv5wsdpu235hqurfdcsx7an9wf6x7undv4h8ggpgw35hqurfdchx6eff9p6nzvfc8q5scqzysxqyz5vqj8xq6wz6dezmunw6qxleuw67ensjnt3fldltrmmkvzurge0dczpn94fkwwh7hkh5wqrhsvfegtvhswn252hn6uw5kx99dyumz4v5n9sp337py2'; - let l2 = new LightningCustodianWallet(); + const l2 = new LightningCustodianWallet(); l2.setSecret(process.env.BLITZHUB); await l2.authorize(); await l2.fetchTransactions(); await l2.fetchBalance(); - let oldBalance = +l2.balance; - let txLen = l2.transactions_raw.length; + const oldBalance = +l2.balance; + const txLen = l2.transactions_raw.length; - let decoded = await l2.decodeInvoice(invoice); + const decoded = await l2.decodeInvoice(invoice); assert.ok(decoded.payment_hash); assert.ok(decoded.description); assert.strictEqual(+decoded.num_satoshis, 0); @@ -354,11 +381,11 @@ describe('LightningCustodianWallet', () => { // then, pay: - let start = +new Date(); + const start = +new Date(); await l2.payInvoice(invoice, 3); - let end = +new Date(); + const end = +new Date(); if ((end - start) / 1000 > 9) { - console.warn('payInvoice took', (end - start) / 1000, 'sec'); + console.warn("payInvoice took", (end - start) / 1000, "sec"); } await l2.fetchTransactions(); @@ -369,13 +396,13 @@ describe('LightningCustodianWallet', () => { assert.strictEqual(oldBalance - l2.balance, 3); }); - it('cant create zemo amt invoices yet', async () => { - let l1 = new LightningCustodianWallet(); + it("cant create zemo amt invoices yet", async () => { + const l1 = new LightningCustodianWallet(); jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; assert.ok(l1.refill_addressess.length === 0); assert.ok(l1._refresh_token_created_ts === 0); assert.ok(l1._access_token_created_ts === 0); - l1.balance = 'FAKE'; + l1.balance = "FAKE"; await l1.createAccount(true); await l1.authorize(); @@ -389,7 +416,7 @@ describe('LightningCustodianWallet', () => { let err = false; try { - await l1.addInvoice(0, 'zero amt inv'); + await l1.addInvoice(0, "zero amt inv"); } catch (_) { err = true; } @@ -397,34 +424,34 @@ describe('LightningCustodianWallet', () => { err = false; try { - await l1.addInvoice(NaN, 'zero amt inv'); + await l1.addInvoice(NaN, "zero amt inv"); } catch (_) { err = true; } assert.ok(err); }); - it('cant pay negative free amount', async () => { + it("cant pay negative free amount", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; if (!process.env.BLITZHUB) { - console.error('process.env.BLITZHUB not set, skipped'); + console.error("process.env.BLITZHUB not set, skipped"); return; } // fetchig invoice from tippin.me : const api = new Frisbee({ - baseURI: 'https://tippin.me', + baseURI: "https://tippin.me" }); - const res = await api.post('/lndreq/newinvoice.php', { + const res = await api.post("/lndreq/newinvoice.php", { headers: { - Origin: 'https://tippin.me', - 'Accept-Encoding': 'gzip, deflate, br', - 'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8', - 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', - Accept: 'application/json, text/javascript, */*; q=0.01', + Origin: "https://tippin.me", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8", + "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", + Accept: "application/json, text/javascript, */*; q=0.01" }, - body: 'userid=1188&username=overtorment&istaco=0&customAmnt=0&customMemo=', + body: "userid=1188&username=overtorment&istaco=0&customAmnt=0&customMemo=" }); let json; @@ -432,18 +459,18 @@ describe('LightningCustodianWallet', () => { if (res && res.body && (json = JSON.parse(res.body)) && json.message) { invoice = json.message; } else { - throw new Error('tippin.me problem: ' + JSON.stringify(res)); + throw new Error("tippin.me problem: " + JSON.stringify(res)); } - let l2 = new LightningCustodianWallet(); + const l2 = new LightningCustodianWallet(); l2.setSecret(process.env.BLITZHUB); await l2.authorize(); await l2.fetchTransactions(); await l2.fetchBalance(); - let oldBalance = +l2.balance; - let txLen = l2.transactions_raw.length; + const oldBalance = +l2.balance; + const txLen = l2.transactions_raw.length; - let decoded = await l2.decodeInvoice(invoice); + const decoded = await l2.decodeInvoice(invoice); assert.ok(decoded.payment_hash); assert.ok(decoded.description); assert.strictEqual(+decoded.num_satoshis, 0); diff --git a/tests/integration/Loc.test.js b/tests/integration/Loc.test.js index 12c5bc8f124..69e0500d160 100644 --- a/tests/integration/Loc.test.js +++ b/tests/integration/Loc.test.js @@ -1,32 +1,34 @@ /* global it, describe */ -let assert = require('assert'); +const assert = require("assert"); -describe('Localization', () => { - it('has all keys in all locales', async () => { - let en = require('../../loc/en'); +describe("Localization", () => { + it("has all keys in all locales", async () => { + const en = require("../../loc/en"); let noErrors = true; - for (let key1 of Object.keys(en)) { - for (let key2 of Object.keys(en[key1])) { + for (const key1 of Object.keys(en)) { + for (const key2 of Object.keys(en[key1])) { // iterating all keys and subkeys in EN locale, which is main - for (let lang of ['es', 'pt_BR', 'pt_PT', 'ru', 'ua']) { + for (const lang of ["es", "pt_BR", "pt_PT", "ru", "ua"]) { // iteratin all locales except EN - let locale = require('../../loc/' + lang); + const locale = require("../../loc/" + lang); - if (typeof locale[key1] === 'undefined') { - console.error('Missing: ' + lang + '.' + key1); + if (typeof locale[key1] === "undefined") { + console.error("Missing: " + lang + "." + key1); noErrors = false; - } else if (typeof locale[key1][key2] === 'undefined') { - console.error('Missing: ' + lang + '.' + key1 + '.' + key2); + } else if (typeof locale[key1][key2] === "undefined") { + console.error("Missing: " + lang + "." + key1 + "." + key2); noErrors = false; } // level 1 & 2 done, doing level 3 (if it exists): - if (typeof en[key1][key2] !== 'string') { - for (let key3 of Object.keys(en[key1][key2])) { - if (typeof locale[key1][key2][key3] === 'undefined') { - console.error('Missing: ' + lang + '.' + key1 + '.' + key2 + '.' + key3); + if (typeof en[key1][key2] !== "string") { + for (const key3 of Object.keys(en[key1][key2])) { + if (typeof locale[key1][key2][key3] === "undefined") { + console.error( + "Missing: " + lang + "." + key1 + "." + key2 + "." + key3 + ); noErrors = false; } } @@ -34,6 +36,6 @@ describe('Localization', () => { } } } - assert.ok(noErrors, 'Some localizations are missing keys'); + assert.ok(noErrors, "Some localizations are missing keys"); }); }); diff --git a/tests/integration/Storage.test.js b/tests/integration/Storage.test.js index f5041b19d94..2f2d8d82ff1 100644 --- a/tests/integration/Storage.test.js +++ b/tests/integration/Storage.test.js @@ -1,50 +1,52 @@ /* global it, jest */ -import { SegwitP2SHWallet, AppStorage } from '../../class'; -import AsyncStorage from '@react-native-community/async-storage'; -global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment -let assert = require('assert'); +import { SegwitP2SHWallet, AppStorage } from "../../class"; +import AsyncStorage from "@react-native-community/async-storage"; + +global.crypto = require("crypto"); // shall be used by tests under nodejs CLI, but not in RN environment +const assert = require("assert"); + jest.useFakeTimers(); -it('Appstorage - loadFromDisk works', async () => { +it("Appstorage - loadFromDisk works", async () => { /** @type {AppStorage} */ - let Storage = new AppStorage(); - let w = new SegwitP2SHWallet(); - w.setLabel('testlabel'); + const Storage = new AppStorage(); + const w = new SegwitP2SHWallet(); + w.setLabel("testlabel"); await w.generate(); Storage.wallets.push(w); await Storage.saveToDisk(); // saved, now trying to load - let Storage2 = new AppStorage(); + const Storage2 = new AppStorage(); await Storage2.loadFromDisk(); assert.strictEqual(Storage2.wallets.length, 1); - assert.strictEqual(Storage2.wallets[0].getLabel(), 'testlabel'); + assert.strictEqual(Storage2.wallets[0].getLabel(), "testlabel"); let isEncrypted = await Storage2.storageIsEncrypted(); assert.ok(!isEncrypted); // emulating encrypted storage (and testing flag) - await AsyncStorage.setItem('data', false); - await AsyncStorage.setItem(AppStorage.FLAG_ENCRYPTED, '1'); - let Storage3 = new AppStorage(); + await AsyncStorage.setItem("data", false); + await AsyncStorage.setItem(AppStorage.FLAG_ENCRYPTED, "1"); + const Storage3 = new AppStorage(); isEncrypted = await Storage3.storageIsEncrypted(); assert.ok(isEncrypted); }); -it('Appstorage - encryptStorage & load encrypted storage works', async () => { +it("Appstorage - encryptStorage & load encrypted storage works", async () => { /** @type {AppStorage} */ - let Storage = new AppStorage(); + const Storage = new AppStorage(); let w = new SegwitP2SHWallet(); - w.setLabel('testlabel'); + w.setLabel("testlabel"); await w.generate(); Storage.wallets.push(w); await Storage.saveToDisk(); let isEncrypted = await Storage.storageIsEncrypted(); assert.ok(!isEncrypted); - await Storage.encryptStorage('password'); + await Storage.encryptStorage("password"); isEncrypted = await Storage.storageIsEncrypted(); - assert.strictEqual(Storage.cachedPassword, 'password'); + assert.strictEqual(Storage.cachedPassword, "password"); assert.ok(isEncrypted); // saved, now trying to load, using good password @@ -52,17 +54,17 @@ it('Appstorage - encryptStorage & load encrypted storage works', async () => { let Storage2 = new AppStorage(); isEncrypted = await Storage2.storageIsEncrypted(); assert.ok(isEncrypted); - let loadResult = await Storage2.loadFromDisk('password'); + let loadResult = await Storage2.loadFromDisk("password"); assert.ok(loadResult); assert.strictEqual(Storage2.wallets.length, 1); - assert.strictEqual(Storage2.wallets[0].getLabel(), 'testlabel'); + assert.strictEqual(Storage2.wallets[0].getLabel(), "testlabel"); // now trying to load, using bad password Storage2 = new AppStorage(); isEncrypted = await Storage2.storageIsEncrypted(); assert.ok(isEncrypted); - loadResult = await Storage2.loadFromDisk('passwordBAD'); + loadResult = await Storage2.loadFromDisk("passwordBAD"); assert.ok(!loadResult); assert.strictEqual(Storage2.wallets.length, 0); @@ -72,48 +74,50 @@ it('Appstorage - encryptStorage & load encrypted storage works', async () => { Storage2 = new AppStorage(); isEncrypted = await Storage2.storageIsEncrypted(); assert.ok(isEncrypted); - loadResult = await Storage2.loadFromDisk('password'); + loadResult = await Storage2.loadFromDisk("password"); assert.ok(loadResult); assert.strictEqual(Storage2.wallets.length, 1); - assert.strictEqual(Storage2.wallets[0].getLabel(), 'testlabel'); + assert.strictEqual(Storage2.wallets[0].getLabel(), "testlabel"); w = new SegwitP2SHWallet(); - w.setLabel('testlabel2'); + w.setLabel("testlabel2"); await w.generate(); Storage2.wallets.push(w); assert.strictEqual(Storage2.wallets.length, 2); - assert.strictEqual(Storage2.wallets[1].getLabel(), 'testlabel2'); + assert.strictEqual(Storage2.wallets[1].getLabel(), "testlabel2"); await Storage2.saveToDisk(); // saved to encrypted storage after load. next load should be successfull Storage2 = new AppStorage(); isEncrypted = await Storage2.storageIsEncrypted(); assert.ok(isEncrypted); - loadResult = await Storage2.loadFromDisk('password'); + loadResult = await Storage2.loadFromDisk("password"); assert.ok(loadResult); assert.strictEqual(Storage2.wallets.length, 2); - assert.strictEqual(Storage2.wallets[0].getLabel(), 'testlabel'); - assert.strictEqual(Storage2.wallets[1].getLabel(), 'testlabel2'); + assert.strictEqual(Storage2.wallets[0].getLabel(), "testlabel"); + assert.strictEqual(Storage2.wallets[1].getLabel(), "testlabel2"); // next, adding new `fake` storage which should be unlocked with `fake` password - let createFakeStorageResult = await Storage2.createFakeStorage('fakePassword'); + const createFakeStorageResult = await Storage2.createFakeStorage( + "fakePassword" + ); assert.ok(createFakeStorageResult); assert.strictEqual(Storage2.wallets.length, 0); - assert.strictEqual(Storage2.cachedPassword, 'fakePassword'); + assert.strictEqual(Storage2.cachedPassword, "fakePassword"); w = new SegwitP2SHWallet(); - w.setLabel('fakewallet'); + w.setLabel("fakewallet"); await w.generate(); Storage2.wallets.push(w); await Storage2.saveToDisk(); // now, will try to load & decrypt with real password and with fake password // real: let Storage3 = new AppStorage(); - loadResult = await Storage3.loadFromDisk('password'); + loadResult = await Storage3.loadFromDisk("password"); assert.ok(loadResult); assert.strictEqual(Storage3.wallets.length, 2); - assert.strictEqual(Storage3.wallets[0].getLabel(), 'testlabel'); + assert.strictEqual(Storage3.wallets[0].getLabel(), "testlabel"); // fake: Storage3 = new AppStorage(); - loadResult = await Storage3.loadFromDisk('fakePassword'); + loadResult = await Storage3.loadFromDisk("fakePassword"); assert.ok(loadResult); assert.strictEqual(Storage3.wallets.length, 1); - assert.strictEqual(Storage3.wallets[0].getLabel(), 'fakewallet'); + assert.strictEqual(Storage3.wallets[0].getLabel(), "fakewallet"); }); diff --git a/tests/integration/WatchOnlyWallet.test.js b/tests/integration/WatchOnlyWallet.test.js index ef307fa272a..ac5f6f8350a 100644 --- a/tests/integration/WatchOnlyWallet.test.js +++ b/tests/integration/WatchOnlyWallet.test.js @@ -1,8 +1,9 @@ /* global it, describe, jasmine, afterAll, beforeAll */ -import { WatchOnlyWallet } from '../../class'; -let assert = require('assert'); -global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js -let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP +import { WatchOnlyWallet } from "../../class"; + +const assert = require("assert"); +global.net = require("net"); // needed by Electrum client. For RN it is proviced in shim.js +const BlueElectrum = require("../../BlueElectrum"); // so it connects ASAP afterAll(async () => { // after all tests we close socket so the test suite can actually terminate @@ -16,24 +17,24 @@ beforeAll(async () => { await BlueElectrum.waitTillConnected(); }); -describe('Watch only wallet', () => { - it('can fetch balance', async () => { - let w = new WatchOnlyWallet(); - w.setSecret('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'); +describe("Watch only wallet", () => { + it("can fetch balance", async () => { + const w = new WatchOnlyWallet(); + w.setSecret("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"); await w.fetchBalance(); assert.ok(w.getBalance() > 16); }); - it('can fetch tx', async () => { + it("can fetch tx", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000; let w = new WatchOnlyWallet(); - w.setSecret('167zK5iZrs1U6piDqubD3FjRqUTM2CZnb8'); + w.setSecret("167zK5iZrs1U6piDqubD3FjRqUTM2CZnb8"); await w.fetchTransactions(); assert.strictEqual(w.getTransactions().length, 233); w = new WatchOnlyWallet(); - w.setSecret('1BiJW1jyUaxcJp2JWwbPLPzB1toPNWTFJV'); + w.setSecret("1BiJW1jyUaxcJp2JWwbPLPzB1toPNWTFJV"); await w.fetchTransactions(); assert.strictEqual(w.getTransactions().length, 2); @@ -42,118 +43,137 @@ describe('Watch only wallet', () => { assert.strictEqual(w.getTransactions().length, 2); }); - it('can fetch complex TXs', async () => { + it("can fetch complex TXs", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 120 * 1000; - let w = new WatchOnlyWallet(); - w.setSecret('3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC'); + const w = new WatchOnlyWallet(); + w.setSecret("3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC"); await w.fetchTransactions(); - for (let tx of w.getTransactions()) { - assert.ok(tx.value, 'incorrect tx.value'); + for (const tx of w.getTransactions()) { + assert.ok(tx.value, "incorrect tx.value"); } }); - it('can validate address', async () => { - let w = new WatchOnlyWallet(); - w.setSecret('12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG'); + it("can validate address", async () => { + const w = new WatchOnlyWallet(); + w.setSecret("12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG"); assert.ok(w.valid()); - w.setSecret('3BDsBDxDimYgNZzsqszNZobqQq3yeUoJf2'); + w.setSecret("3BDsBDxDimYgNZzsqszNZobqQq3yeUoJf2"); assert.ok(w.valid()); - w.setSecret('not valid'); + w.setSecret("not valid"); assert.ok(!w.valid()); - w.setSecret('xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps'); + w.setSecret( + "xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps" + ); assert.ok(w.valid()); - w.setSecret('ypub6XRzrn3HB1tjhhvrHbk1vnXCecZEdXohGzCk3GXwwbDoJ3VBzZ34jNGWbC6WrS7idXrYjjXEzcPDX5VqnHEnuNf5VAXgLfSaytMkJ2rwVqy'); + w.setSecret( + "ypub6XRzrn3HB1tjhhvrHbk1vnXCecZEdXohGzCk3GXwwbDoJ3VBzZ34jNGWbC6WrS7idXrYjjXEzcPDX5VqnHEnuNf5VAXgLfSaytMkJ2rwVqy" + ); assert.ok(w.valid()); - w.setSecret('zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP'); + w.setSecret( + "zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP" + ); assert.ok(w.valid()); }); - it('can fetch balance & transactions from zpub HD', async () => { + it("can fetch balance & transactions from zpub HD", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; - let w = new WatchOnlyWallet(); - w.setSecret('zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP'); + const w = new WatchOnlyWallet(); + w.setSecret( + "zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP" + ); await w.fetchBalance(); assert.strictEqual(w.getBalance(), 200000); await w.fetchTransactions(); assert.strictEqual(w.getTransactions().length, 4); - assert.ok((await w.getAddressAsync()).startsWith('bc1')); + assert.ok((await w.getAddressAsync()).startsWith("bc1")); }); - it('can create PSBT base64 without signature for HW wallet', async () => { - let w = new WatchOnlyWallet(); - w.setSecret('zpub6rjLjQVqVnj7crz9E4QWj4WgczmEseJq22u2B6k2HZr6NE2PQx3ZYg8BnbjN9kCfHymSeMd2EpwpM5iiz5Nrb3TzvddxW2RMcE3VXdVaXHk'); + it("can create PSBT base64 without signature for HW wallet", async () => { + const w = new WatchOnlyWallet(); + w.setSecret( + "zpub6rjLjQVqVnj7crz9E4QWj4WgczmEseJq22u2B6k2HZr6NE2PQx3ZYg8BnbjN9kCfHymSeMd2EpwpM5iiz5Nrb3TzvddxW2RMcE3VXdVaXHk" + ); // zpub provided by Stepan @ CryptoAdvance w.init(); - const changeAddress = 'bc1quuafy8htjjj263cvpj7md84magzmc8svmh8lrm'; + const changeAddress = "bc1quuafy8htjjj263cvpj7md84magzmc8svmh8lrm"; // hardcoding so we wont have to call w.getChangeAddressAsync() const utxos = [ { height: 596736, value: 20000, - address: 'bc1qhu8jqyzfazgatpctqn44xr7pdd3mdx6qy2r6xa', - txId: '7f3b9e032a84413d7a5027b0d020f8acf80ad28f68b5bce8fa8ac357248c5b80', - vout: 0, - }, + address: "bc1qhu8jqyzfazgatpctqn44xr7pdd3mdx6qy2r6xa", + txId: + "7f3b9e032a84413d7a5027b0d020f8acf80ad28f68b5bce8fa8ac357248c5b80", + vout: 0 + } ]; // hardcoding utxo so we wont have to call w.fetchUtxo() and w.getUtxo() - let { psbt } = await w.createTransaction( + const { psbt } = await w.createTransaction( utxos, - [{ address: 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu', value: 5000 }], + [{ address: "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", value: 5000 }], 1, - changeAddress, + changeAddress ); assert.strictEqual( psbt.toBase64(), - 'cHNidP8BAHECAAAAAYBbjCRXw4r66Ly1aI/SCvis+CDQsCdQej1BhCoDnjt/AAAAAAAAAACAAogTAAAAAAAAFgAUwM681sPTyox13F7GLr5VMw75EOK3OQAAAAAAABYAFOc6kh7rlKStRwwMvbaeu+oFvB4MAAAAAAABAR8gTgAAAAAAABYAFL8PIBBJ6JHVhwsE61MPwWtjtptAIgYDWOHbOE3D4KiuoR7kHtmTtFZ7KXQB+8zb51QALLJxTx8YAAAAAFQAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgM005BVD8MgH5kiSGnwXSfzaxLeDSl3y17Vhrx3F/9XxBgAAAAAVAAAgAAAAIAAAACAAQAAAAAAAAAA', + "cHNidP8BAHECAAAAAYBbjCRXw4r66Ly1aI/SCvis+CDQsCdQej1BhCoDnjt/AAAAAAAAAACAAogTAAAAAAAAFgAUwM681sPTyox13F7GLr5VMw75EOK3OQAAAAAAABYAFOc6kh7rlKStRwwMvbaeu+oFvB4MAAAAAAABAR8gTgAAAAAAABYAFL8PIBBJ6JHVhwsE61MPwWtjtptAIgYDWOHbOE3D4KiuoR7kHtmTtFZ7KXQB+8zb51QALLJxTx8YAAAAAFQAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgM005BVD8MgH5kiSGnwXSfzaxLeDSl3y17Vhrx3F/9XxBgAAAAAVAAAgAAAAIAAAACAAQAAAAAAAAAA" ); }); - it('can combine signed PSBT and prepare it for broadcast', async () => { - let w = new WatchOnlyWallet(); - w.setSecret('zpub6rjLjQVqVnj7crz9E4QWj4WgczmEseJq22u2B6k2HZr6NE2PQx3ZYg8BnbjN9kCfHymSeMd2EpwpM5iiz5Nrb3TzvddxW2RMcE3VXdVaXHk'); + it("can combine signed PSBT and prepare it for broadcast", async () => { + const w = new WatchOnlyWallet(); + w.setSecret( + "zpub6rjLjQVqVnj7crz9E4QWj4WgczmEseJq22u2B6k2HZr6NE2PQx3ZYg8BnbjN9kCfHymSeMd2EpwpM5iiz5Nrb3TzvddxW2RMcE3VXdVaXHk" + ); w.init(); const signedPsbt = - 'cHNidP8BAHECAAAAAYBbjCRXw4r66Ly1aI/SCvis+CDQsCdQej1BhCoDnjt/AAAAAAAAAACAAogTAAAAAAAAFgAUwM681sPTyox13F7GLr5VMw75EOK3OQAAAAAAABYAFOc6kh7rlKStRwwMvbaeu+oFvB4MAAAAAAAiAgNY4ds4TcPgqK6hHuQe2ZO0VnspdAH7zNvnVAAssnFPH0cwRAIgPR9zZzNTnfPqZJifyUwdM2cWW8PZqCnSCsfCePlZ2aoCIFbhr/5P/bS6eGQZtX3+6q+nUO6KaSKYgaaZrUZENF6BAQAAAA=='; + "cHNidP8BAHECAAAAAYBbjCRXw4r66Ly1aI/SCvis+CDQsCdQej1BhCoDnjt/AAAAAAAAAACAAogTAAAAAAAAFgAUwM681sPTyox13F7GLr5VMw75EOK3OQAAAAAAABYAFOc6kh7rlKStRwwMvbaeu+oFvB4MAAAAAAAiAgNY4ds4TcPgqK6hHuQe2ZO0VnspdAH7zNvnVAAssnFPH0cwRAIgPR9zZzNTnfPqZJifyUwdM2cWW8PZqCnSCsfCePlZ2aoCIFbhr/5P/bS6eGQZtX3+6q+nUO6KaSKYgaaZrUZENF6BAQAAAA=="; const unsignedPsbt = - 'cHNidP8BAHECAAAAAYBbjCRXw4r66Ly1aI/SCvis+CDQsCdQej1BhCoDnjt/AAAAAAAAAACAAogTAAAAAAAAFgAUwM681sPTyox13F7GLr5VMw75EOK3OQAAAAAAABYAFOc6kh7rlKStRwwMvbaeu+oFvB4MAAAAAAABAR8gTgAAAAAAABYAFL8PIBBJ6JHVhwsE61MPwWtjtptAIgYDWOHbOE3D4KiuoR7kHtmTtFZ7KXQB+8zb51QALLJxTx8YAAAAAFQAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgM005BVD8MgH5kiSGnwXSfzaxLeDSl3y17Vhrx3F/9XxBgAAAAAVAAAgAAAAIAAAACAAQAAAAAAAAAA'; + "cHNidP8BAHECAAAAAYBbjCRXw4r66Ly1aI/SCvis+CDQsCdQej1BhCoDnjt/AAAAAAAAAACAAogTAAAAAAAAFgAUwM681sPTyox13F7GLr5VMw75EOK3OQAAAAAAABYAFOc6kh7rlKStRwwMvbaeu+oFvB4MAAAAAAABAR8gTgAAAAAAABYAFL8PIBBJ6JHVhwsE61MPwWtjtptAIgYDWOHbOE3D4KiuoR7kHtmTtFZ7KXQB+8zb51QALLJxTx8YAAAAAFQAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgM005BVD8MgH5kiSGnwXSfzaxLeDSl3y17Vhrx3F/9XxBgAAAAAVAAAgAAAAIAAAACAAQAAAAAAAAAA"; const Tx = w.combinePsbt(unsignedPsbt, signedPsbt); assert.strictEqual( Tx.toHex(), - '02000000000101805b8c2457c38afae8bcb5688fd20af8acf820d0b027507a3d41842a039e3b7f000000000000000080028813000000000000160014c0cebcd6c3d3ca8c75dc5ec62ebe55330ef910e2b739000000000000160014e73a921eeb94a4ad470c0cbdb69ebbea05bc1e0c0247304402203d1f736733539df3ea64989fc94c1d3367165bc3d9a829d20ac7c278f959d9aa022056e1affe4ffdb4ba786419b57dfeeaafa750ee8a69229881a699ad4644345e8101210358e1db384dc3e0a8aea11ee41ed993b4567b297401fbccdbe754002cb2714f1f00000000', + "02000000000101805b8c2457c38afae8bcb5688fd20af8acf820d0b027507a3d41842a039e3b7f000000000000000080028813000000000000160014c0cebcd6c3d3ca8c75dc5ec62ebe55330ef910e2b739000000000000160014e73a921eeb94a4ad470c0cbdb69ebbea05bc1e0c0247304402203d1f736733539df3ea64989fc94c1d3367165bc3d9a829d20ac7c278f959d9aa022056e1affe4ffdb4ba786419b57dfeeaafa750ee8a69229881a699ad4644345e8101210358e1db384dc3e0a8aea11ee41ed993b4567b297401fbccdbe754002cb2714f1f00000000" ); }); - it('can fetch balance & transactions from ypub HD', async () => { + it("can fetch balance & transactions from ypub HD", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; - let w = new WatchOnlyWallet(); - w.setSecret('ypub6Y9u3QCRC1HkZv3stNxcQVwmw7vC7KX5Ldz38En5P88RQbesP2oy16hNyQocVCfYRQPxdHcd3pmu9AFhLv7NdChWmw5iNLryZ2U6EEHdnfo'); + const w = new WatchOnlyWallet(); + w.setSecret( + "ypub6Y9u3QCRC1HkZv3stNxcQVwmw7vC7KX5Ldz38En5P88RQbesP2oy16hNyQocVCfYRQPxdHcd3pmu9AFhLv7NdChWmw5iNLryZ2U6EEHdnfo" + ); await w.fetchBalance(); assert.strictEqual(w.getBalance(), 51432); await w.fetchTransactions(); assert.strictEqual(w.getTransactions().length, 107); - assert.ok((await w.getAddressAsync()).startsWith('3')); + assert.ok((await w.getAddressAsync()).startsWith("3")); }); - it('can fetch balance & transactions from xpub HD', async () => { + it("can fetch balance & transactions from xpub HD", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 100 * 1000; - let w = new WatchOnlyWallet(); - w.setSecret('xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps'); + const w = new WatchOnlyWallet(); + w.setSecret( + "xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps" + ); await w.fetchBalance(); assert.strictEqual(w.getBalance(), 0); await w.fetchTransactions(); assert.strictEqual(w.getTransactions().length, 4); - assert.ok((await w.getAddressAsync()).startsWith('1')); + assert.ok((await w.getAddressAsync()).startsWith("1")); }); - it('can fetch large HD', async () => { + it("can fetch large HD", async () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 500 * 1000; - let w = new WatchOnlyWallet(); - w.setSecret('ypub6WnnYxkQCGeowv4BXq9Y9PHaXgHMJg9TkFaDJkunhcTAfbDw8z3LvV9kFNHGjeVaEoGdsSJgaMWpUBvYvpYGMJd43gTK5opecVVkvLwKttx'); + const w = new WatchOnlyWallet(); + w.setSecret( + "ypub6WnnYxkQCGeowv4BXq9Y9PHaXgHMJg9TkFaDJkunhcTAfbDw8z3LvV9kFNHGjeVaEoGdsSJgaMWpUBvYvpYGMJd43gTK5opecVVkvLwKttx" + ); await w.fetchBalance(); await w.fetchTransactions(); diff --git a/tests/integration/hd-segwit-bech32-transaction.test.js b/tests/integration/hd-segwit-bech32-transaction.test.js index 148c4358856..5ce906c3e4b 100644 --- a/tests/integration/hd-segwit-bech32-transaction.test.js +++ b/tests/integration/hd-segwit-bech32-transaction.test.js @@ -1,10 +1,16 @@ /* global it, describe, jasmine, afterAll, beforeAll */ -import { HDSegwitBech32Wallet, SegwitP2SHWallet, HDSegwitBech32Transaction, SegwitBech32Wallet } from '../../class'; -const bitcoin = require('bitcoinjs-lib'); -global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment -let assert = require('assert'); -global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js -let BlueElectrum = require('../../BlueElectrum'); +import { + HDSegwitBech32Wallet, + SegwitP2SHWallet, + HDSegwitBech32Transaction, + SegwitBech32Wallet +} from "../../class"; + +const bitcoin = require("bitcoinjs-lib"); +global.crypto = require("crypto"); // shall be used by tests under nodejs CLI, but not in RN environment +const assert = require("assert"); +global.net = require("net"); // needed by Electrum client. For RN it is proviced in shim.js +const BlueElectrum = require("../../BlueElectrum"); afterAll(async () => { // after all tests we close socket so the test suite can actually terminate @@ -18,16 +24,19 @@ beforeAll(async () => { await BlueElectrum.waitTillConnected(); }); -describe('HDSegwitBech32Transaction', () => { - it('can decode & check sequence', async function() { +describe("HDSegwitBech32Transaction", () => { + it("can decode & check sequence", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; - let T = new HDSegwitBech32Transaction(null, 'e9ef58baf4cff3ad55913a360c2fa1fd124309c59dcd720cdb172ce46582097b'); + let T = new HDSegwitBech32Transaction( + null, + "e9ef58baf4cff3ad55913a360c2fa1fd124309c59dcd720cdb172ce46582097b" + ); assert.strictEqual(await T.getMaxUsedSequence(), 0xffffffff); assert.strictEqual(await T.isSequenceReplaceable(), false); // 881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e T = new HDSegwitBech32Transaction( - '02000000000102f1155666b534f7cb476a0523a45dc8731d38d56b5b08e877c968812423fbd7f3010000000000000000d8a2882a692ee759b43e6af48ac152dd3410cc4b7d25031e83b3396c16ffbc8900000000000000000002400d03000000000017a914e286d58e53f9247a4710e51232cce0686f16873c870695010000000000160014d3e2ecbf4d91321794e0297e0284c47527cf878b02483045022100d18dc865fb4d087004d021d480b983b8afb177a1934ce4cd11cf97b03e17944f02206d7310687a84aab5d4696d535bca69c2db4449b48feb55fff028aa004f2d1744012103af4b208608c75f38e78f6e5abfbcad9c360fb60d3e035193b2cd0cdc8fc0155c0247304402207556e859845df41d897fe442f59b6106c8fa39c74ba5b7b8e3268ab0aebf186f0220048a9f3742339c44a1e5c78b491822b96070bcfda3f64db9dc6434f8e8068475012102456e5223ed3884dc6b0e152067fd836e3eb1485422eda45558bf83f59c6ad09f00000000', + "02000000000102f1155666b534f7cb476a0523a45dc8731d38d56b5b08e877c968812423fbd7f3010000000000000000d8a2882a692ee759b43e6af48ac152dd3410cc4b7d25031e83b3396c16ffbc8900000000000000000002400d03000000000017a914e286d58e53f9247a4710e51232cce0686f16873c870695010000000000160014d3e2ecbf4d91321794e0297e0284c47527cf878b02483045022100d18dc865fb4d087004d021d480b983b8afb177a1934ce4cd11cf97b03e17944f02206d7310687a84aab5d4696d535bca69c2db4449b48feb55fff028aa004f2d1744012103af4b208608c75f38e78f6e5abfbcad9c360fb60d3e035193b2cd0cdc8fc0155c0247304402207556e859845df41d897fe442f59b6106c8fa39c74ba5b7b8e3268ab0aebf186f0220048a9f3742339c44a1e5c78b491822b96070bcfda3f64db9dc6434f8e8068475012102456e5223ed3884dc6b0e152067fd836e3eb1485422eda45558bf83f59c6ad09f00000000" ); assert.strictEqual(await T.getMaxUsedSequence(), 0); assert.strictEqual(await T.isSequenceReplaceable(), true); @@ -35,147 +44,185 @@ describe('HDSegwitBech32Transaction', () => { assert.ok((await T.getRemoteConfirmationsNum()) >= 292); }); - it('can tell if its our transaction', async function() { + it("can tell if its our transaction", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { - console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP84 not set, skipped"); return; } - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP84); assert.ok(hd.validateMnemonic()); await hd.fetchTransactions(); - let tt = new HDSegwitBech32Transaction(null, '881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e', hd); + let tt = new HDSegwitBech32Transaction( + null, + "881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e", + hd + ); assert.ok(await tt.isOurTransaction()); - tt = new HDSegwitBech32Transaction(null, '89bcff166c39b3831e03257d4bcc1034dd52c18af46a3eb459e72e692a88a2d8', hd); + tt = new HDSegwitBech32Transaction( + null, + "89bcff166c39b3831e03257d4bcc1034dd52c18af46a3eb459e72e692a88a2d8", + hd + ); assert.ok(!(await tt.isOurTransaction())); }); - it('can tell tx info', async function() { + it("can tell tx info", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { - console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP84 not set, skipped"); return; } - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP84); await hd.fetchBalance(); await hd.fetchTransactions(); - let tt = new HDSegwitBech32Transaction(null, '881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e', hd); + const tt = new HDSegwitBech32Transaction( + null, + "881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e", + hd + ); - let { fee, feeRate, targets, changeAmount, utxos } = await tt.getInfo(); + const { fee, feeRate, targets, changeAmount, utxos } = await tt.getInfo(); assert.strictEqual(fee, 4464); assert.strictEqual(changeAmount, 103686); assert.strictEqual(feeRate, 12); assert.strictEqual(targets.length, 1); assert.strictEqual(targets[0].value, 200000); - assert.strictEqual(targets[0].address, '3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC'); + assert.strictEqual( + targets[0].address, + "3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC" + ); assert.strictEqual( JSON.stringify(utxos), JSON.stringify([ { vout: 1, value: 108150, - txId: 'f3d7fb23248168c977e8085b6bd5381d73c85da423056a47cbf734b5665615f1', - address: 'bc1qahhgjtxexjx9t0e5pjzqwtjnxexzl6f5an38hq', + txId: + "f3d7fb23248168c977e8085b6bd5381d73c85da423056a47cbf734b5665615f1", + address: "bc1qahhgjtxexjx9t0e5pjzqwtjnxexzl6f5an38hq" }, { vout: 0, value: 200000, - txId: '89bcff166c39b3831e03257d4bcc1034dd52c18af46a3eb459e72e692a88a2d8', - address: 'bc1qvh44cwd2v7zld8ef9ld5rs5zafmejuslp6yd73', - }, - ]), + txId: + "89bcff166c39b3831e03257d4bcc1034dd52c18af46a3eb459e72e692a88a2d8", + address: "bc1qvh44cwd2v7zld8ef9ld5rs5zafmejuslp6yd73" + } + ]) ); }); - it('can do RBF - cancel tx', async function() { + it("can do RBF - cancel tx", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { - console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP84 not set, skipped"); return; } - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP84); await hd.fetchBalance(); await hd.fetchTransactions(); - let tt = new HDSegwitBech32Transaction(null, '881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e', hd); + const tt = new HDSegwitBech32Transaction( + null, + "881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e", + hd + ); assert.strictEqual(await tt.canCancelTx(), true); - let { tx } = await tt.createRBFcancelTx(15); + const { tx } = await tt.createRBFcancelTx(15); - let createdTx = bitcoin.Transaction.fromHex(tx.toHex()); + const createdTx = bitcoin.Transaction.fromHex(tx.toHex()); assert.strictEqual(createdTx.ins.length, 2); assert.strictEqual(createdTx.outs.length, 1); - let addr = SegwitBech32Wallet.scriptPubKeyToAddress(createdTx.outs[0].script); + const addr = SegwitBech32Wallet.scriptPubKeyToAddress( + createdTx.outs[0].script + ); assert.ok(hd.weOwnAddress(addr)); - let actualFeerate = (108150 + 200000 - createdTx.outs[0].value) / (tx.toHex().length / 2); + const actualFeerate = + (108150 + 200000 - createdTx.outs[0].value) / (tx.toHex().length / 2); assert.strictEqual(Math.round(actualFeerate), 15); - let tt2 = new HDSegwitBech32Transaction(tx.toHex(), null, hd); + const tt2 = new HDSegwitBech32Transaction(tx.toHex(), null, hd); assert.strictEqual(await tt2.canCancelTx(), false); // newly created cancel tx is not cancellable anymore }); - it('can do RBF - bumpfees tx', async function() { + it("can do RBF - bumpfees tx", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { - console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP84 not set, skipped"); return; } - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP84); await hd.fetchBalance(); await hd.fetchTransactions(); - let tt = new HDSegwitBech32Transaction(null, '881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e', hd); + const tt = new HDSegwitBech32Transaction( + null, + "881c54edd95cbdd1583d6b9148eb35128a47b64a2e67a5368a649d6be960f08e", + hd + ); assert.strictEqual(await tt.canCancelTx(), true); - let { tx } = await tt.createRBFbumpFee(17); + const { tx } = await tt.createRBFbumpFee(17); - let createdTx = bitcoin.Transaction.fromHex(tx.toHex()); + const createdTx = bitcoin.Transaction.fromHex(tx.toHex()); assert.strictEqual(createdTx.ins.length, 2); assert.strictEqual(createdTx.outs.length, 2); - let addr0 = SegwitP2SHWallet.scriptPubKeyToAddress(createdTx.outs[0].script); + const addr0 = SegwitP2SHWallet.scriptPubKeyToAddress( + createdTx.outs[0].script + ); assert.ok(!hd.weOwnAddress(addr0)); - assert.strictEqual(addr0, '3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC'); // dest address - let addr1 = SegwitBech32Wallet.scriptPubKeyToAddress(createdTx.outs[1].script); + assert.strictEqual(addr0, "3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC"); // dest address + const addr1 = SegwitBech32Wallet.scriptPubKeyToAddress( + createdTx.outs[1].script + ); assert.ok(hd.weOwnAddress(addr1)); - let actualFeerate = (108150 + 200000 - (createdTx.outs[0].value + createdTx.outs[1].value)) / (tx.toHex().length / 2); + const actualFeerate = + (108150 + 200000 - (createdTx.outs[0].value + createdTx.outs[1].value)) / + (tx.toHex().length / 2); assert.strictEqual(Math.round(actualFeerate), 17); - let tt2 = new HDSegwitBech32Transaction(tx.toHex(), null, hd); + const tt2 = new HDSegwitBech32Transaction(tx.toHex(), null, hd); assert.strictEqual(await tt2.canCancelTx(), true); // new tx is still cancellable since we only bumped fees }); - it('can do CPFP - bump fees', async function() { + it("can do CPFP - bump fees", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { - console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP84 not set, skipped"); return; } - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP84); await hd.fetchBalance(); await hd.fetchTransactions(); - let tt = new HDSegwitBech32Transaction(null, '2ec8a1d0686dcccffc102ba5453a28d99c8a1e5061c27b41f5c0a23b0b27e75f', hd); + const tt = new HDSegwitBech32Transaction( + null, + "2ec8a1d0686dcccffc102ba5453a28d99c8a1e5061c27b41f5c0a23b0b27e75f", + hd + ); assert.ok(await tt.isToUsTransaction()); - let { unconfirmedUtxos, fee: oldFee } = await tt.getInfo(); + const { unconfirmedUtxos, fee: oldFee } = await tt.getInfo(); assert.strictEqual( JSON.stringify(unconfirmedUtxos), @@ -183,14 +230,16 @@ describe('HDSegwitBech32Transaction', () => { { vout: 0, value: 200000, - txId: '2ec8a1d0686dcccffc102ba5453a28d99c8a1e5061c27b41f5c0a23b0b27e75f', - address: 'bc1qvlmgrq0gtatanmas0tswrsknllvupq2g844ss2', - }, - ]), + txId: + "2ec8a1d0686dcccffc102ba5453a28d99c8a1e5061c27b41f5c0a23b0b27e75f", + address: "bc1qvlmgrq0gtatanmas0tswrsknllvupq2g844ss2" + } + ]) ); - let { tx, fee } = await tt.createCPFPbumpFee(20); - let avgFeeRate = (oldFee + fee) / (tt._txhex.length / 2 + tx.toHex().length / 2); + const { tx, fee } = await tt.createCPFPbumpFee(20); + const avgFeeRate = + (oldFee + fee) / (tt._txhex.length / 2 + tx.toHex().length / 2); assert.ok(Math.round(avgFeeRate) >= 20); }); }); diff --git a/tests/integration/hd-segwit-bech32-wallet.test.js b/tests/integration/hd-segwit-bech32-wallet.test.js index d4f8828a4c9..862eca91d7b 100644 --- a/tests/integration/hd-segwit-bech32-wallet.test.js +++ b/tests/integration/hd-segwit-bech32-wallet.test.js @@ -1,9 +1,10 @@ /* global it, describe, jasmine, afterAll, beforeAll */ -import { HDSegwitBech32Wallet } from '../../class'; -global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment -let assert = require('assert'); -global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js -let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP +import { HDSegwitBech32Wallet } from "../../class"; + +global.crypto = require("crypto"); // shall be used by tests under nodejs CLI, but not in RN environment +const assert = require("assert"); +global.net = require("net"); // needed by Electrum client. For RN it is proviced in shim.js +const BlueElectrum = require("../../BlueElectrum"); // so it connects ASAP afterAll(async () => { // after all tests we close socket so the test suite can actually terminate @@ -17,33 +18,66 @@ beforeAll(async () => { await BlueElectrum.waitTillConnected(); }); -describe('Bech32 Segwit HD (BIP84)', () => { - it('can create', async function() { +describe("Bech32 Segwit HD (BIP84)", () => { + it("can create", async function() { jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; - let mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; - let hd = new HDSegwitBech32Wallet(); + const mnemonic = + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; + const hd = new HDSegwitBech32Wallet(); hd.setSecret(mnemonic); assert.strictEqual(true, hd.validateMnemonic()); assert.strictEqual( - 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs', - hd.getXpub(), + "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs", + hd.getXpub() ); - assert.strictEqual(hd._getExternalWIFByIndex(0), 'KyZpNDKnfs94vbrwhJneDi77V6jF64PWPF8x5cdJb8ifgg2DUc9d'); - assert.strictEqual(hd._getExternalWIFByIndex(1), 'Kxpf5b8p3qX56DKEe5NqWbNUP9MnqoRFzZwHRtsFqhzuvUJsYZCy'); - assert.strictEqual(hd._getInternalWIFByIndex(0), 'KxuoxufJL5csa1Wieb2kp29VNdn92Us8CoaUG3aGtPtcF3AzeXvF'); + assert.strictEqual( + hd._getExternalWIFByIndex(0), + "KyZpNDKnfs94vbrwhJneDi77V6jF64PWPF8x5cdJb8ifgg2DUc9d" + ); + assert.strictEqual( + hd._getExternalWIFByIndex(1), + "Kxpf5b8p3qX56DKEe5NqWbNUP9MnqoRFzZwHRtsFqhzuvUJsYZCy" + ); + assert.strictEqual( + hd._getInternalWIFByIndex(0), + "KxuoxufJL5csa1Wieb2kp29VNdn92Us8CoaUG3aGtPtcF3AzeXvF" + ); assert.ok(hd._getInternalWIFByIndex(0) !== hd._getInternalWIFByIndex(1)); - assert.strictEqual(hd._getExternalAddressByIndex(0), 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu'); - assert.strictEqual(hd._getExternalAddressByIndex(1), 'bc1qnjg0jd8228aq7egyzacy8cys3knf9xvrerkf9g'); - assert.strictEqual(hd._getInternalAddressByIndex(0), 'bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el'); - assert.ok(hd._getInternalAddressByIndex(0) !== hd._getInternalAddressByIndex(1)); + assert.strictEqual( + hd._getExternalAddressByIndex(0), + "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu" + ); + assert.strictEqual( + hd._getExternalAddressByIndex(1), + "bc1qnjg0jd8228aq7egyzacy8cys3knf9xvrerkf9g" + ); + assert.strictEqual( + hd._getInternalAddressByIndex(0), + "bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el" + ); + assert.ok( + hd._getInternalAddressByIndex(0) !== hd._getInternalAddressByIndex(1) + ); - assert.strictEqual(hd._getDerivationPathByAddress(hd._getExternalAddressByIndex(0)), "m/84'/0'/0'/0/0"); - assert.strictEqual(hd._getDerivationPathByAddress(hd._getExternalAddressByIndex(1)), "m/84'/0'/0'/0/1"); - assert.strictEqual(hd._getDerivationPathByAddress(hd._getInternalAddressByIndex(0)), "m/84'/0'/0'/1/0"); - assert.strictEqual(hd._getDerivationPathByAddress(hd._getInternalAddressByIndex(1)), "m/84'/0'/0'/1/1"); + assert.strictEqual( + hd._getDerivationPathByAddress(hd._getExternalAddressByIndex(0)), + "m/84'/0'/0'/0/0" + ); + assert.strictEqual( + hd._getDerivationPathByAddress(hd._getExternalAddressByIndex(1)), + "m/84'/0'/0'/0/1" + ); + assert.strictEqual( + hd._getDerivationPathByAddress(hd._getInternalAddressByIndex(0)), + "m/84'/0'/0'/1/0" + ); + assert.strictEqual( + hd._getDerivationPathByAddress(hd._getInternalAddressByIndex(1)), + "m/84'/0'/0'/1/1" + ); assert.ok(hd._lastBalanceFetch === 0); await hd.fetchBalance(); @@ -51,17 +85,23 @@ describe('Bech32 Segwit HD (BIP84)', () => { assert.ok(hd._lastBalanceFetch > 0); // checking that internal pointer and async address getter return the same address - let freeAddress = await hd.getAddressAsync(); + const freeAddress = await hd.getAddressAsync(); assert.strictEqual(hd.next_free_address_index, 0); - assert.strictEqual(hd._getExternalAddressByIndex(hd.next_free_address_index), freeAddress); - let freeChangeAddress = await hd.getChangeAddressAsync(); + assert.strictEqual( + hd._getExternalAddressByIndex(hd.next_free_address_index), + freeAddress + ); + const freeChangeAddress = await hd.getChangeAddressAsync(); assert.strictEqual(hd.next_free_change_address_index, 0); - assert.strictEqual(hd._getInternalAddressByIndex(hd.next_free_change_address_index), freeChangeAddress); + assert.strictEqual( + hd._getInternalAddressByIndex(hd.next_free_change_address_index), + freeChangeAddress + ); }); - it('can fetch balance', async function() { + it("can fetch balance", async function() { if (!process.env.HD_MNEMONIC) { - console.error('process.env.HD_MNEMONIC not set, skipped'); + console.error("process.env.HD_MNEMONIC not set, skipped"); return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 90 * 1000; @@ -70,19 +110,37 @@ describe('Bech32 Segwit HD (BIP84)', () => { assert.ok(hd.validateMnemonic()); assert.strictEqual( - 'zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP', - hd.getXpub(), + "zpub6r7jhKKm7BAVx3b3nSnuadY1WnshZYkhK8gKFoRLwK9rF3Mzv28BrGcCGA3ugGtawi1WLb2vyjQAX9ZTDGU5gNk2bLdTc3iEXr6tzR1ipNP", + hd.getXpub() ); - assert.strictEqual(hd._getExternalAddressByIndex(0), 'bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p'); - assert.strictEqual(hd._getExternalAddressByIndex(1), 'bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh'); - assert.strictEqual(hd._getInternalAddressByIndex(0), 'bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy'); - assert.strictEqual(hd._getInternalAddressByIndex(1), 'bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r'); + assert.strictEqual( + hd._getExternalAddressByIndex(0), + "bc1qvd6w54sydc08z3802svkxr7297ez7cusd6266p" + ); + assert.strictEqual( + hd._getExternalAddressByIndex(1), + "bc1qt4t9xl2gmjvxgmp5gev6m8e6s9c85979ta7jeh" + ); + assert.strictEqual( + hd._getInternalAddressByIndex(0), + "bc1qcg6e26vtzja0h8up5w2m7utex0fsu4v0e0e7uy" + ); + assert.strictEqual( + hd._getInternalAddressByIndex(1), + "bc1qwp58x4c9e5cplsnw5096qzdkae036ug7a34x3r" + ); await hd.fetchBalance(); assert.strictEqual(hd.getBalance(), 200000); - assert.strictEqual(await hd.getAddressAsync(), hd._getExternalAddressByIndex(2)); - assert.strictEqual(await hd.getChangeAddressAsync(), hd._getInternalAddressByIndex(2)); + assert.strictEqual( + await hd.getAddressAsync(), + hd._getExternalAddressByIndex(2) + ); + assert.strictEqual( + await hd.getChangeAddressAsync(), + hd._getInternalAddressByIndex(2) + ); assert.strictEqual(hd.next_free_address_index, 2); assert.strictEqual(hd.next_free_change_address_index, 2); @@ -90,19 +148,25 @@ describe('Bech32 Segwit HD (BIP84)', () => { hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC); - assert.strictEqual(await hd.getAddressAsync(), hd._getExternalAddressByIndex(2)); - assert.strictEqual(await hd.getChangeAddressAsync(), hd._getInternalAddressByIndex(2)); + assert.strictEqual( + await hd.getAddressAsync(), + hd._getExternalAddressByIndex(2) + ); + assert.strictEqual( + await hd.getChangeAddressAsync(), + hd._getInternalAddressByIndex(2) + ); assert.strictEqual(hd.next_free_address_index, 2); assert.strictEqual(hd.next_free_change_address_index, 2); }); - it('can fetch transactions', async function() { + it("can fetch transactions", async function() { if (!process.env.HD_MNEMONIC) { - console.error('process.env.HD_MNEMONIC not set, skipped'); + console.error("process.env.HD_MNEMONIC not set, skipped"); return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 90 * 1000; - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC); assert.ok(hd.validateMnemonic()); @@ -116,7 +180,7 @@ describe('Bech32 Segwit HD (BIP84)', () => { assert.strictEqual(hd.timeToRefreshBalance(), false); assert.strictEqual(hd.getTransactions().length, 4); - for (let tx of hd.getTransactions()) { + for (const tx of hd.getTransactions()) { assert.ok(tx.hash); assert.strictEqual(tx.value, 50000); assert.ok(tx.received); @@ -124,19 +188,19 @@ describe('Bech32 Segwit HD (BIP84)', () => { } }); - it('can fetch UTXO', async () => { + it("can fetch UTXO", async () => { if (!process.env.HD_MNEMONIC) { - console.error('process.env.HD_MNEMONIC not set, skipped'); + console.error("process.env.HD_MNEMONIC not set, skipped"); return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 90 * 1000; - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC); assert.ok(hd.validateMnemonic()); await hd.fetchBalance(); await hd.fetchUtxo(); - let utxo = hd.getUtxo(); + const utxo = hd.getUtxo(); assert.strictEqual(utxo.length, 4); assert.ok(utxo[0].txId); assert.ok(utxo[0].vout === 0 || utxo[0].vout === 1); @@ -144,58 +208,73 @@ describe('Bech32 Segwit HD (BIP84)', () => { assert.ok(utxo[0].address); }); - it('can generate addresses only via zpub', function() { - let zpub = 'zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs'; - let hd = new HDSegwitBech32Wallet(); + it("can generate addresses only via zpub", function() { + const zpub = + "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"; + const hd = new HDSegwitBech32Wallet(); hd._xpub = zpub; - assert.strictEqual(hd._getExternalAddressByIndex(0), 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu'); - assert.strictEqual(hd._getExternalAddressByIndex(1), 'bc1qnjg0jd8228aq7egyzacy8cys3knf9xvrerkf9g'); - assert.strictEqual(hd._getInternalAddressByIndex(0), 'bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el'); - assert.ok(hd._getInternalAddressByIndex(0) !== hd._getInternalAddressByIndex(1)); + assert.strictEqual( + hd._getExternalAddressByIndex(0), + "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu" + ); + assert.strictEqual( + hd._getExternalAddressByIndex(1), + "bc1qnjg0jd8228aq7egyzacy8cys3knf9xvrerkf9g" + ); + assert.strictEqual( + hd._getInternalAddressByIndex(0), + "bc1q8c6fshw2dlwun7ekn9qwf37cu2rn755upcp6el" + ); + assert.ok( + hd._getInternalAddressByIndex(0) !== hd._getInternalAddressByIndex(1) + ); }); - it('can generate', async () => { - let hd = new HDSegwitBech32Wallet(); - let hashmap = {}; + it("can generate", async () => { + const hd = new HDSegwitBech32Wallet(); + const hashmap = {}; for (let c = 0; c < 1000; c++) { await hd.generate(); - let secret = hd.getSecret(); + const secret = hd.getSecret(); if (hashmap[secret]) { - throw new Error('Duplicate secret generated!'); + throw new Error("Duplicate secret generated!"); } hashmap[secret] = 1; - assert.ok(secret.split(' ').length === 12 || secret.split(' ').length === 24); + assert.ok( + secret.split(" ").length === 12 || secret.split(" ").length === 24 + ); } - let hd2 = new HDSegwitBech32Wallet(); + const hd2 = new HDSegwitBech32Wallet(); hd2.setSecret(hd.getSecret()); assert.ok(hd2.validateMnemonic()); }); - it('can catch up with externally modified wallet', async () => { + it("can catch up with externally modified wallet", async () => { if (!process.env.HD_MNEMONIC_BIP84) { - console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP84 not set, skipped"); return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 90 * 1000; - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP84); assert.ok(hd.validateMnemonic()); await hd.fetchBalance(); - let oldBalance = hd.getBalance(); + const oldBalance = hd.getBalance(); await hd.fetchTransactions(); - let oldTransactions = hd.getTransactions(); + const oldTransactions = hd.getTransactions(); // now, mess with internal state, make it 'obsolete' - hd._txs_by_external_index['2'].pop(); - hd._txs_by_internal_index['16'].pop(); - hd._txs_by_internal_index['17'] = []; + hd._txs_by_external_index["2"].pop(); + hd._txs_by_internal_index["16"].pop(); + hd._txs_by_internal_index["17"] = []; - for (let c = 17; c < 100; c++) hd._balances_by_internal_index[c] = { c: 0, u: 0 }; - hd._balances_by_external_index['2'].c = 1000000; + for (let c = 17; c < 100; c++) + hd._balances_by_internal_index[c] = { c: 0, u: 0 }; + hd._balances_by_external_index["2"].c = 1000000; assert.ok(hd.getBalance() !== oldBalance); assert.ok(hd.getTransactions().length !== oldTransactions.length); @@ -208,13 +287,13 @@ describe('Bech32 Segwit HD (BIP84)', () => { assert.strictEqual(hd.getTransactions().length, oldTransactions.length); }); - it('can work with fauty zpub', async () => { + it("can work with fauty zpub", async () => { if (!process.env.FAULTY_ZPUB) { - console.error('process.env.FAULTY_ZPUB not set, skipped'); + console.error("process.env.FAULTY_ZPUB not set, skipped"); return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 90 * 1000; - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd._xpub = process.env.FAULTY_ZPUB; await hd.fetchBalance(); @@ -223,24 +302,25 @@ describe('Bech32 Segwit HD (BIP84)', () => { assert.ok(hd.getTransactions().length >= 76); }); - it('can fetchBalance, fetchTransactions, fetchUtxo and create transactions', async () => { + it("can fetchBalance, fetchTransactions, fetchUtxo and create transactions", async () => { if (!process.env.HD_MNEMONIC_BIP84) { - console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); + console.error("process.env.HD_MNEMONIC_BIP84 not set, skipped"); return; } jasmine.DEFAULT_TIMEOUT_INTERVAL = 90 * 1000; - let hd = new HDSegwitBech32Wallet(); + const hd = new HDSegwitBech32Wallet(); hd.setSecret(process.env.HD_MNEMONIC_BIP84); assert.ok(hd.validateMnemonic()); assert.strictEqual( hd.getXpub(), - 'zpub6qoWjSiZRHzSYPGYJ6EzxEXJXP1b2Rj9syWwJZFNCmupMwkbSAWSBk3UvSkJyQLEhQpaBAwvhmNj3HPKpwCJiTBB9Tutt46FtEmjL2DoU3J', + "zpub6qoWjSiZRHzSYPGYJ6EzxEXJXP1b2Rj9syWwJZFNCmupMwkbSAWSBk3UvSkJyQLEhQpaBAwvhmNj3HPKpwCJiTBB9Tutt46FtEmjL2DoU3J" ); let start = +new Date(); await hd.fetchBalance(); let end = +new Date(); - end - start > 5000 && console.warn('fetchBalance took', (end - start) / 1000, 'sec'); + end - start > 5000 && + console.warn("fetchBalance took", (end - start) / 1000, "sec"); assert.ok(hd.next_free_change_address_index > 0); assert.ok(hd.next_free_address_index > 0); @@ -248,66 +328,102 @@ describe('Bech32 Segwit HD (BIP84)', () => { start = +new Date(); await hd.fetchTransactions(); end = +new Date(); - end - start > 15000 && console.warn('fetchTransactions took', (end - start) / 1000, 'sec'); + end - start > 15000 && + console.warn("fetchTransactions took", (end - start) / 1000, "sec"); start = +new Date(); await hd.fetchBalance(); end = +new Date(); - end - start > 2000 && console.warn('warm fetchBalance took', (end - start) / 1000, 'sec'); + end - start > 2000 && + console.warn("warm fetchBalance took", (end - start) / 1000, "sec"); global.debug = true; start = +new Date(); await hd.fetchTransactions(); end = +new Date(); - end - start > 2000 && console.warn('warm fetchTransactions took', (end - start) / 1000, 'sec'); + end - start > 2000 && + console.warn("warm fetchTransactions took", (end - start) / 1000, "sec"); let txFound = 0; - for (let tx of hd.getTransactions()) { - if (tx.hash === 'e9ef58baf4cff3ad55913a360c2fa1fd124309c59dcd720cdb172ce46582097b') { + for (const tx of hd.getTransactions()) { + if ( + tx.hash === + "e9ef58baf4cff3ad55913a360c2fa1fd124309c59dcd720cdb172ce46582097b" + ) { assert.strictEqual(tx.value, -129545); - assert.strictEqual(tx.inputs[0].addresses[0], 'bc1qffcl35r05wyf06meu3dalfevawx559n0ufrxcw'); - assert.strictEqual(tx.inputs[1].addresses[0], 'bc1qtvh8mjcfdg9224nx4wu3sw7fmmtmy2k3jhdeul'); - assert.strictEqual(tx.inputs[2].addresses[0], 'bc1qhe03zgvq4fmfw8l2qq2zu4dxyhgyukcz6k2a5w'); + assert.strictEqual( + tx.inputs[0].addresses[0], + "bc1qffcl35r05wyf06meu3dalfevawx559n0ufrxcw" + ); + assert.strictEqual( + tx.inputs[1].addresses[0], + "bc1qtvh8mjcfdg9224nx4wu3sw7fmmtmy2k3jhdeul" + ); + assert.strictEqual( + tx.inputs[2].addresses[0], + "bc1qhe03zgvq4fmfw8l2qq2zu4dxyhgyukcz6k2a5w" + ); txFound++; } - if (tx.hash === 'e112771fd43962abfe4e4623bf788d6d95ff1bd0f9b56a6a41fb9ed4dacc75f1') { + if ( + tx.hash === + "e112771fd43962abfe4e4623bf788d6d95ff1bd0f9b56a6a41fb9ed4dacc75f1" + ) { assert.strictEqual(tx.value, 1000000); - assert.strictEqual(tx.inputs[0].addresses[0], '3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC'); - assert.strictEqual(tx.inputs[1].addresses[0], '3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC'); + assert.strictEqual( + tx.inputs[0].addresses[0], + "3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC" + ); + assert.strictEqual( + tx.inputs[1].addresses[0], + "3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC" + ); txFound++; } - if (tx.hash === 'c94bdec21c72d3441245caa164b00315b131f6b72513369f4be1b00b9fb99cc5') { - assert.strictEqual(tx.inputs[0].addresses[0], '16Nf5X77RbFz9Mb6t2GFqxs3twQN1joBkD'); + if ( + tx.hash === + "c94bdec21c72d3441245caa164b00315b131f6b72513369f4be1b00b9fb99cc5" + ) { + assert.strictEqual( + tx.inputs[0].addresses[0], + "16Nf5X77RbFz9Mb6t2GFqxs3twQN1joBkD" + ); txFound++; } - if (tx.hash === '51fc225ddf24f7e124f034637f46442645ca7ea2c442b28124d4bcdd04e30195') { - assert.strictEqual(tx.inputs[0].addresses[0], '3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC'); + if ( + tx.hash === + "51fc225ddf24f7e124f034637f46442645ca7ea2c442b28124d4bcdd04e30195" + ) { + assert.strictEqual( + tx.inputs[0].addresses[0], + "3NLnALo49CFEF4tCRhCvz45ySSfz3UktZC" + ); txFound++; } } assert.strictEqual(txFound, 4); await hd.fetchUtxo(); - let changeAddress = await hd.getChangeAddressAsync(); - assert.ok(changeAddress && changeAddress.startsWith('bc1')); + const changeAddress = await hd.getChangeAddressAsync(); + assert.ok(changeAddress && changeAddress.startsWith("bc1")); - let { tx, inputs, outputs, fee } = hd.createTransaction( + const { tx, inputs, outputs, fee } = hd.createTransaction( hd.getUtxo(), - [{ address: 'bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu', value: 51000 }], + [{ address: "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu", value: 51000 }], 13, - changeAddress, + changeAddress ); assert.strictEqual(Math.round(fee / tx.byteLength()), 13); let totalInput = 0; - for (let inp of inputs) { + for (const inp of inputs) { totalInput += inp.value; } assert.strictEqual(outputs.length, 2); let totalOutput = 0; - for (let outp of outputs) { + for (const outp of outputs) { totalOutput += outp.value; } diff --git a/up-build-number.js b/up-build-number.js index d6a13aefa29..bf8d5ba9f80 100644 --- a/up-build-number.js +++ b/up-build-number.js @@ -1,6 +1,7 @@ -let fs = require('fs'); -var appjson = require('./app.json'); +const fs = require("fs"); +const appjson = require("./app.json"); + appjson.expo.ios.buildNumber++; -appjson.expo.ios.buildNumber = appjson.expo.ios.buildNumber + ''; // casting to string -console.log(appjson.expo.version, '(', appjson.expo.ios.buildNumber, ')'); -fs.writeFileSync('./app.json', JSON.stringify(appjson, null, 2)); +appjson.expo.ios.buildNumber = appjson.expo.ios.buildNumber + ""; // casting to string +console.log(appjson.expo.version, "(", appjson.expo.ios.buildNumber, ")"); +fs.writeFileSync("./app.json", JSON.stringify(appjson, null, 2));