diff --git a/BlueElectrum.js b/BlueElectrum.js index 3330f9d91..a3f009842 100644 --- a/BlueElectrum.js +++ b/BlueElectrum.js @@ -1,4 +1,5 @@ import AsyncStorage from '@react-native-community/async-storage'; +import { AppStorage } from './class'; const ElectrumClient = require('electrum-client'); let bitcoin = require('bitcoinjs-lib'); let reverse = require('buffer-reverse'); @@ -27,6 +28,11 @@ let wasConnectedAtLeastOnce = false; async function connectMain() { let usingPeer = await getRandomHardcodedPeer(); + let savedPeer = await getSavedPeer(); + if (savedPeer && savedPeer.host && savedPeer.tcp) { + usingPeer = savedPeer; + } + try { console.log('begin connection:', JSON.stringify(usingPeer)); mainClient = new ElectrumClient(usingPeer.tcp, usingPeer.host, 'tcp'); @@ -69,6 +75,12 @@ async function getRandomHardcodedPeer() { return hardcodedPeers[(hardcodedPeers.length * Math.random()) | 0]; } +async function getSavedPeer() { + let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST); + let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT); + return { host, tcp: port }; +} + /** * Returns random electrum server out of list of servers * previous electrum server told us. Nearly half of them is @@ -114,6 +126,15 @@ module.exports.getBalanceByAddress = async function(address) { return balance; }; +module.exports.getConfig = async function() { + if (!mainClient) throw new Error('Electrum client is not connected'); + return { + host: mainClient.host, + port: mainClient.port, + status: mainClient.status, + }; +}; + /** * * @param address {String} @@ -345,6 +366,28 @@ module.exports.broadcastV2 = async function(hex) { return mainClient.blockchainTransaction_broadcast(hex); }; +/** + * + * @param host + * @param tcpPort + * @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'); + try { + await client.connect(); + await client.server_version('2.7.11', '1.4'); + await client.server_ping(); + + client.keepAlive = () => {}; // dirty hack to make it stop reconnecting + client.reconnect = () => {}; // dirty hack to make it stop reconnecting + client.close(); + return true; + } catch (_) { + return false; + } +}; + module.exports.forceDisconnect = () => { mainClient.keepAlive = () => {}; // dirty hack to make it stop reconnecting mainClient.reconnect = () => {}; // dirty hack to make it stop reconnecting diff --git a/MainBottomTabs.js b/MainBottomTabs.js index 0e222bc95..72d4aae06 100644 --- a/MainBottomTabs.js +++ b/MainBottomTabs.js @@ -9,6 +9,7 @@ import Currency from './screen/settings/currency'; import EncryptStorage from './screen/settings/encryptStorage'; import PlausibleDeniability from './screen/plausibledeniability'; import LightningSettings from './screen/settings/lightningSettings'; +import ElectrumSettings from './screen/settings/electrumSettings'; import WalletsList from './screen/wallets/list'; import WalletTransactions from './screen/wallets/transactions'; import AddWallet from './screen/wallets/add'; @@ -123,6 +124,10 @@ const WalletsStackNavigator = createStackNavigator( screen: LightningSettings, path: 'LightningSettings', }, + ElectrumSettings: { + screen: ElectrumSettings, + path: 'ElectrumSettings', + }, LNDViewInvoice: { screen: LNDViewInvoice, swipeEnabled: false, diff --git a/class/app-storage.js b/class/app-storage.js index 7f6059909..346494a82 100644 --- a/class/app-storage.js +++ b/class/app-storage.js @@ -18,6 +18,8 @@ export class AppStorage { 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'; diff --git a/loc/cs_CZ.js b/loc/cs_CZ.js index 3548c305e..82cb301bf 100644 --- a/loc/cs_CZ.js +++ b/loc/cs_CZ.js @@ -186,6 +186,8 @@ module.exports = { '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 BlueWallet', language: 'Jazyk', diff --git a/loc/da_DK.js b/loc/da_DK.js index 8feae4719..9a26f4a9c 100644 --- a/loc/da_DK.js +++ b/loc/da_DK.js @@ -186,6 +186,8 @@ module.exports = { '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', diff --git a/loc/de_DE.js b/loc/de_DE.js index 65bf72f7c..82cb15b77 100644 --- a/loc/de_DE.js +++ b/loc/de_DE.js @@ -188,6 +188,8 @@ module.exports = { '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', diff --git a/loc/el.js b/loc/el.js index 6c5a9e6de..26ce61c20 100644 --- a/loc/el.js +++ b/loc/el.js @@ -188,6 +188,8 @@ module.exports = { lightning_settings_explain: 'Για να συνδεθείτε στον δικό σας κόμβο LND παρακαλούμε εγκαταστήστε το LndHub' + ' και βάλτε το URL του εδώ. Αφήστε το κενό για να χρησιμοποιήσετε το LNDHub της BlueWallet (lndhub.io). Αφού σώσετε τις ρυθμίσεις τυχόν νέα πορτοφόλια που θα δημιουργήσετε θα συνδεθούν στο LNDHub που επιλέξατε.', + electrum_settings: 'Electrum Settings', + electrum_settings_explain: 'Set to blank to use default', save: 'Σώσε', about: 'Σχετικά', language: 'Γλώσσα', diff --git a/loc/en.js b/loc/en.js index 6ad4e0f3b..ee5c28c33 100644 --- a/loc/en.js +++ b/loc/en.js @@ -186,6 +186,8 @@ module.exports = { lightning_settings_explain: 'To connect to your own LND node please install LndHub' + " and put its URL here in settings. Leave blank to use BlueWallet's LNDHub (lndhub.io). Wallets created after saving changes will connect to the specified LNDHub.", + electrum_settings: 'Electrum Settings', + electrum_settings_explain: 'Set to blank to use default', save: 'Save', about: 'About', language: 'Language', diff --git a/loc/es.js b/loc/es.js index 22acea6ac..bf7f100bc 100644 --- a/loc/es.js +++ b/loc/es.js @@ -189,6 +189,8 @@ module.exports = { '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: 'Sobre nosotros', language: 'Idioma', diff --git a/loc/fi_FI.js b/loc/fi_FI.js index 67a0f2d68..4d9b95c7c 100644 --- a/loc/fi_FI.js +++ b/loc/fi_FI.js @@ -188,6 +188,8 @@ module.exports = { lightning_settings_explain: 'Yhdistääksesi omaan LND noodiin, asenna LndHub' + ' ja laita sen URL tänne. Jätä tyhjäksi käyttääksesi BlueWalletin 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', diff --git a/loc/fr_FR.js b/loc/fr_FR.js index d1b831304..cbfbc43bb 100644 --- a/loc/fr_FR.js +++ b/loc/fr_FR.js @@ -188,6 +188,8 @@ module.exports = { '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', diff --git a/loc/hr_HR.js b/loc/hr_HR.js index 554336a83..5bc30145b 100644 --- a/loc/hr_HR.js +++ b/loc/hr_HR.js @@ -184,6 +184,8 @@ module.exports = { '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', diff --git a/loc/id_ID.js b/loc/id_ID.js index 155920ad7..5fd71472d 100644 --- a/loc/id_ID.js +++ b/loc/id_ID.js @@ -185,6 +185,8 @@ module.exports = { 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', diff --git a/loc/it.js b/loc/it.js index eabf94608..d5c2172ab 100644 --- a/loc/it.js +++ b/loc/it.js @@ -188,6 +188,8 @@ module.exports = { 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', diff --git a/loc/jp_JP.js b/loc/jp_JP.js index 92a470152..5669d0f30 100644 --- a/loc/jp_JP.js +++ b/loc/jp_JP.js @@ -186,6 +186,8 @@ module.exports = { '他の LND ノードへ接続するには LndHub をインストール後、' + 'URL を入力してください。既定の設定を使用するには空欄にします' + 'ndHub\n (lndhub.io)', + electrum_settings: 'Electrum Settings', + electrum_settings_explain: 'Set to blank to use default', save: '保存', about: 'BlueWallet について', language: '言語', diff --git a/loc/nb_NO.js b/loc/nb_NO.js index 6be8a8ca0..5f1a7ad9c 100644 --- a/loc/nb_NO.js +++ b/loc/nb_NO.js @@ -186,6 +186,8 @@ module.exports = { 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 BlueWallets 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', diff --git a/loc/nl_NL.js b/loc/nl_NL.js index 22f86f517..e0f2134d3 100644 --- a/loc/nl_NL.js +++ b/loc/nl_NL.js @@ -187,6 +187,8 @@ module.exports = { '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', diff --git a/loc/pt_BR.js b/loc/pt_BR.js index 0fe2637c1..f61ba810b 100644 --- a/loc/pt_BR.js +++ b/loc/pt_BR.js @@ -191,6 +191,8 @@ module.exports = { '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 BlueWallet (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', diff --git a/loc/pt_PT.js b/loc/pt_PT.js index 66171e19f..e5bf8ce51 100644 --- a/loc/pt_PT.js +++ b/loc/pt_PT.js @@ -189,6 +189,8 @@ module.exports = { '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: 'Sobre', language: 'Idioma', diff --git a/loc/ru.js b/loc/ru.js index b4150463d..91db7f7ae 100644 --- a/loc/ru.js +++ b/loc/ru.js @@ -188,6 +188,8 @@ module.exports = { 'Чтобы подключиться к своему узлу LND, пожалуйста, установи LndHub' + ' и добавь его URL в настройки. Оставь поле пустым, чтобы использоавать стандартный ' + 'LndHub\n (lndhub.io)', + electrum_settings: 'Electrum Settings', + electrum_settings_explain: 'Set to blank to use default', save: 'Сохранить', about: 'О программе', language: 'Язык', diff --git a/loc/sv_SE.js b/loc/sv_SE.js index 612d2aadc..7a1b39aaa 100644 --- a/loc/sv_SE.js +++ b/loc/sv_SE.js @@ -185,6 +185,8 @@ module.exports = { lightning_settings_explain: '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 BlueWallet'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', diff --git a/loc/th_TH.js b/loc/th_TH.js index 0a8d45f44..ab2df0493 100644 --- a/loc/th_TH.js +++ b/loc/th_TH.js @@ -186,6 +186,8 @@ module.exports = { 'กรณีที่ต้องการต่อเชื่อมไปยังไลท์นิงโนดของท่านเอง กรุณาติดตั้ง LndHub ของท่าน' + ' และไส่ URL ที่นี่. ระบบจะใช้ LndHub ของ lndhub.io ในกรณืที่ท่าน ' + ' ไม่ตั้งค่าใดๆ', + electrum_settings: 'Electrum Settings', + electrum_settings_explain: 'Set to blank to use default', save: 'บันทึก', about: 'เกี่ยวกับ', language: 'ภาษา', diff --git a/loc/tr_TR.js b/loc/tr_TR.js index 226f5ba9e..a3ea5b6ff 100644 --- a/loc/tr_TR.js +++ b/loc/tr_TR.js @@ -186,6 +186,8 @@ module.exports = { lightning_settings_explain: 'Kendi LND düğümünüze bağlanmak için lütfen LndHubı yükleyin.' + " ve URL’sini buraya, ayarlara yazın. BlueWallet'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', diff --git a/loc/ua.js b/loc/ua.js index 63b8c131c..74951ea4b 100644 --- a/loc/ua.js +++ b/loc/ua.js @@ -188,6 +188,8 @@ module.exports = { '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: 'Мова', diff --git a/loc/zh_cn.js b/loc/zh_cn.js index 3a584c462..68ea3f80a 100755 --- a/loc/zh_cn.js +++ b/loc/zh_cn.js @@ -181,6 +181,8 @@ module.exports = { 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: '语言', diff --git a/screen/settings/electrumSettings.js b/screen/settings/electrumSettings.js new file mode 100644 index 000000000..ad68a155c --- /dev/null +++ b/screen/settings/electrumSettings.js @@ -0,0 +1,135 @@ +/* global alert */ +import React, { Component } from 'react'; +import { View, TextInput } from 'react-native'; +import { AppStorage } from '../../class'; +import AsyncStorage from '@react-native-community/async-storage'; +import { BlueLoading, BlueSpacing20, BlueButton, SafeBlueArea, BlueCard, BlueNavigationStyle, BlueText } from '../../BlueComponents'; +import PropTypes from 'prop-types'; +let loc = require('../../loc'); +let BlueElectrum = require('../../BlueElectrum'); + +export default class ElectrumSettings extends Component { + static navigationOptions = () => ({ + ...BlueNavigationStyle(), + title: loc.settings.electrum_settings, + }); + + constructor(props) { + super(props); + this.state = { + isLoading: true, + config: {}, + }; + } + + async componentDidMount() { + let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST); + let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT); + + this.setState({ + isLoading: false, + host, + port, + }); + + await this.setState({ + 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 : ''; + try { + 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.'); + } + } catch (_) {} + this.setState({ isLoading: false }); + }); + }; + + render() { + return ( + + + {loc.settings.electrum_settings_explain} + + + + this.setState({ host: text })} + numberOfLines={1} + style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36 }} + editable={!this.state.isLoading} + underlineColorAndroid="transparent" + /> + + + + this.setState({ port: text })} + numberOfLines={1} + style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36 }} + editable={!this.state.isLoading} + underlineColorAndroid="transparent" + /> + + + + {this.state.isLoading ? : } + + + + + Currently using: + Host: {this.state.config.host} + Port: {this.state.config.port} + Connected: {(this.state.config.status === 1 && 'Yes') || 'No'} + + + ); + } +} + +ElectrumSettings.propTypes = { + navigation: PropTypes.shape({ + navigate: PropTypes.func, + goBack: PropTypes.func, + }), +}; diff --git a/screen/settings/settings.js b/screen/settings/settings.js index ec73c17e0..4b711ffec 100644 --- a/screen/settings/settings.js +++ b/screen/settings/settings.js @@ -65,6 +65,9 @@ export default class Settings extends Component { this.props.navigation.navigate('Currency')}> + this.props.navigation.navigate('ElectrumSettings')}> + + this.setState({ showAdvancedOptions: !this.state.showAdvancedOptions })}> diff --git a/tests/integration/Electrum.test.js b/tests/integration/Electrum.test.js index de09417b3..708dee9e1 100644 --- a/tests/integration/Electrum.test.js +++ b/tests/integration/Electrum.test.js @@ -23,6 +23,10 @@ beforeAll(async () => { }); describe('Electrum', () => { + it('ElectrumClient can test connection', async () => { + assert.ok(await BlueElectrum.testConnection('electrum1.bluewallet.io', '50001')); + }); + it('ElectrumClient can connect and query', async () => { const ElectrumClient = require('electrum-client');