mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-03 20:07:11 +01:00
ADD: support for Electrum Personal Server (SSL connection)
This commit is contained in:
parent
c0f3d99147
commit
6b188d24ca
13 changed files with 193 additions and 86 deletions
|
@ -6,7 +6,7 @@ let reverse = require('buffer-reverse');
|
||||||
let BigNumber = require('bignumber.js');
|
let BigNumber = require('bignumber.js');
|
||||||
|
|
||||||
const storageKey = 'ELECTRUM_PEERS';
|
const storageKey = 'ELECTRUM_PEERS';
|
||||||
const defaultPeer = { host: 'electrum1.bluewallet.io', tcp: '50001' };
|
const defaultPeer = { host: 'electrum1.bluewallet.io', ssl: '443' };
|
||||||
const hardcodedPeers = [
|
const hardcodedPeers = [
|
||||||
// { host: 'noveltybobble.coinjoined.com', tcp: '50001' }, // down
|
// { host: 'noveltybobble.coinjoined.com', tcp: '50001' }, // down
|
||||||
// { host: 'electrum.be', tcp: '50001' },
|
// { host: 'electrum.be', tcp: '50001' },
|
||||||
|
@ -16,27 +16,27 @@ const hardcodedPeers = [
|
||||||
// { host: 'Bitkoins.nl', tcp: '50001' }, // down
|
// { host: 'Bitkoins.nl', tcp: '50001' }, // down
|
||||||
// { host: 'fullnode.coinkite.com', tcp: '50001' },
|
// { host: 'fullnode.coinkite.com', tcp: '50001' },
|
||||||
// { host: 'preperfect.eleCTruMioUS.com', tcp: '50001' }, // down
|
// { host: 'preperfect.eleCTruMioUS.com', tcp: '50001' }, // down
|
||||||
{ host: 'electrum1.bluewallet.io', tcp: '50001' },
|
{ host: 'electrum1.bluewallet.io', ssl: '443' },
|
||||||
{ host: 'electrum1.bluewallet.io', tcp: '50001' }, // 2x weight
|
{ host: 'electrum1.bluewallet.io', ssl: '443' }, // 2x weight
|
||||||
{ host: 'electrum2.bluewallet.io', tcp: '50001' },
|
{ host: 'electrum2.bluewallet.io', ssl: '443' },
|
||||||
{ host: 'electrum3.bluewallet.io', tcp: '50001' },
|
{ host: 'electrum3.bluewallet.io', ssl: '443' },
|
||||||
{ host: 'electrum3.bluewallet.io', tcp: '50001' }, // 2x weight
|
{ host: 'electrum3.bluewallet.io', ssl: '443' }, // 2x weight
|
||||||
];
|
];
|
||||||
|
|
||||||
let mainClient = false;
|
let mainClient: ElectrumClient = false;
|
||||||
let mainConnected = false;
|
let mainConnected = false;
|
||||||
let wasConnectedAtLeastOnce = false;
|
let wasConnectedAtLeastOnce = false;
|
||||||
|
|
||||||
async function connectMain() {
|
async function connectMain() {
|
||||||
let usingPeer = await getRandomHardcodedPeer();
|
let usingPeer = await getRandomHardcodedPeer();
|
||||||
let savedPeer = await getSavedPeer();
|
let savedPeer = await getSavedPeer();
|
||||||
if (savedPeer && savedPeer.host && savedPeer.tcp) {
|
if (savedPeer && savedPeer.host && (savedPeer.tcp || savedPeer.ssl)) {
|
||||||
usingPeer = savedPeer;
|
usingPeer = savedPeer;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('begin connection:', JSON.stringify(usingPeer));
|
console.log('begin connection:', JSON.stringify(usingPeer));
|
||||||
mainClient = new ElectrumClient(usingPeer.tcp, usingPeer.host, 'tcp');
|
mainClient = new ElectrumClient(usingPeer.ssl || usingPeer.tcp, usingPeer.host, usingPeer.ssl ? 'tls' : 'tcp');
|
||||||
mainClient.onError = function(e) {
|
mainClient.onError = function(e) {
|
||||||
console.log('ElectrumClient error: ' + e);
|
console.log('ElectrumClient error: ' + e);
|
||||||
mainConnected = false;
|
mainConnected = false;
|
||||||
|
@ -78,7 +78,8 @@ async function getRandomHardcodedPeer() {
|
||||||
async function getSavedPeer() {
|
async function getSavedPeer() {
|
||||||
let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST);
|
let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST);
|
||||||
let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT);
|
let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT);
|
||||||
return { host, tcp: port };
|
let sslPort = await AsyncStorage.getItem(AppStorage.ELECTRUM_SSL_PORT);
|
||||||
|
return { host, tcp: port, ssl: sslPort };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -391,17 +392,15 @@ module.exports.broadcastV2 = async function(hex) {
|
||||||
*
|
*
|
||||||
* @param host
|
* @param host
|
||||||
* @param tcpPort
|
* @param tcpPort
|
||||||
|
* @param sslPort
|
||||||
* @returns {Promise<boolean>} Whether provided host:port is a valid electrum server
|
* @returns {Promise<boolean>} Whether provided host:port is a valid electrum server
|
||||||
*/
|
*/
|
||||||
module.exports.testConnection = async function(host, tcpPort) {
|
module.exports.testConnection = async function(host, tcpPort, sslPort) {
|
||||||
let client = new ElectrumClient(tcpPort, host, 'tcp');
|
let client = new ElectrumClient(sslPort || tcpPort, host, sslPort ? 'tls' : 'tcp');
|
||||||
try {
|
try {
|
||||||
await client.connect();
|
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();
|
await client.server_ping();
|
||||||
|
|
||||||
client.keepAlive = () => {}; // dirty hack to make it stop reconnecting
|
|
||||||
client.reconnect = () => {}; // dirty hack to make it stop reconnecting
|
|
||||||
client.close();
|
client.close();
|
||||||
return true;
|
return true;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
|
@ -410,8 +409,6 @@ module.exports.testConnection = async function(host, tcpPort) {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.forceDisconnect = () => {
|
module.exports.forceDisconnect = () => {
|
||||||
mainClient.keepAlive = () => {}; // dirty hack to make it stop reconnecting
|
|
||||||
mainClient.reconnect = () => {}; // dirty hack to make it stop reconnecting
|
|
||||||
mainClient.close();
|
mainClient.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ export class AppStorage {
|
||||||
static LNDHUB = 'lndhub';
|
static LNDHUB = 'lndhub';
|
||||||
static ELECTRUM_HOST = 'electrum_host';
|
static ELECTRUM_HOST = 'electrum_host';
|
||||||
static ELECTRUM_TCP_PORT = 'electrum_tcp_port';
|
static ELECTRUM_TCP_PORT = 'electrum_tcp_port';
|
||||||
|
static ELECTRUM_SSL_PORT = 'electrum_ssl_port';
|
||||||
static PREFERRED_CURRENCY = 'preferredCurrency';
|
static PREFERRED_CURRENCY = 'preferredCurrency';
|
||||||
static ADVANCED_MODE_ENABLED = 'advancedmodeenabled';
|
static ADVANCED_MODE_ENABLED = 'advancedmodeenabled';
|
||||||
static DELETE_WALLET_AFTER_UNINSTALL = 'deleteWalletAfterUninstall';
|
static DELETE_WALLET_AFTER_UNINSTALL = 'deleteWalletAfterUninstall';
|
||||||
|
|
99
package-lock.json
generated
99
package-lock.json
generated
|
@ -4374,8 +4374,8 @@
|
||||||
"integrity": "sha512-NK9DBBYEBb5f9D7zXI0hiE941gq3wkBeQmXs1ingigA/jnTg5mhwY2Z5egwA+ZI8OLGKCx0h1Cl8/xeuIBuLlg=="
|
"integrity": "sha512-NK9DBBYEBb5f9D7zXI0hiE941gq3wkBeQmXs1ingigA/jnTg5mhwY2Z5egwA+ZI8OLGKCx0h1Cl8/xeuIBuLlg=="
|
||||||
},
|
},
|
||||||
"electrum-client": {
|
"electrum-client": {
|
||||||
"version": "git+https://github.com/BlueWallet/rn-electrum-client.git#d194ff69195ccc86f72088ea3712179b4be9cbb4",
|
"version": "git+https://github.com/BlueWallet/rn-electrum-client.git#aa73cd8bb3f2d6aefd7c054cb08d5bf5151d1cbb",
|
||||||
"from": "git+https://github.com/BlueWallet/rn-electrum-client.git"
|
"from": "git+https://github.com/BlueWallet/rn-electrum-client.git#aa73cd8bb3f2d6aefd7c054cb08d5bf5151d1cbb"
|
||||||
},
|
},
|
||||||
"elliptic": {
|
"elliptic": {
|
||||||
"version": "6.5.2",
|
"version": "6.5.2",
|
||||||
|
@ -6767,9 +6767,9 @@
|
||||||
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
|
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
|
||||||
},
|
},
|
||||||
"ip-regex": {
|
"ip-regex": {
|
||||||
"version": "1.0.3",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-3.0.0.tgz",
|
||||||
"integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0="
|
"integrity": "sha512-T8wDtjy+Qf2TAPDQmBp0eGKJ8GavlWlUnamr3wRn6vvdZlKVuJXXMlSncYFRYgVHOM3If5NR1H4+OvVQU9Idvg=="
|
||||||
},
|
},
|
||||||
"is": {
|
"is": {
|
||||||
"version": "0.2.7",
|
"version": "0.2.7",
|
||||||
|
@ -11697,33 +11697,86 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-native-tcp": {
|
"react-native-tcp": {
|
||||||
"version": "git+https://github.com/aprock/react-native-tcp.git#6a3b1bc702bf1d40287274ac32698335a8fba61a",
|
"version": "git+https://github.com/BlueWallet/react-native-tcp.git#113433d505063d58a17317e925f03f65e7fc5c3d",
|
||||||
"from": "git+https://github.com/aprock/react-native-tcp.git",
|
"from": "git+https://github.com/BlueWallet/react-native-tcp.git",
|
||||||
"requires": {
|
"requires": {
|
||||||
"base64-js": "0.0.8",
|
"base64-js": "1.3.0",
|
||||||
"buffer": "^5.0.0",
|
"buffer": "5.2.1",
|
||||||
"events": "^1.0.2",
|
"events": "3.0.0",
|
||||||
"ip-regex": "^1.0.3",
|
"ip-regex": "3.0.0",
|
||||||
"process": "^0.11.9",
|
"process": "0.11.10",
|
||||||
"util": "^0.10.3"
|
"stream-browserify": "2.0.1",
|
||||||
|
"util": "0.11.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "0.0.8",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
|
||||||
"integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg="
|
"integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw=="
|
||||||
},
|
},
|
||||||
"inherits": {
|
"buffer": {
|
||||||
"version": "2.0.3",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
"integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "^1.0.2",
|
||||||
|
"ieee754": "^1.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA=="
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "2.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||||
|
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.3",
|
||||||
|
"isarray": "~1.0.0",
|
||||||
|
"process-nextick-args": "~2.0.0",
|
||||||
|
"safe-buffer": "~5.1.1",
|
||||||
|
"string_decoder": "~1.1.1",
|
||||||
|
"util-deprecate": "~1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
},
|
||||||
|
"stream-browserify": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "~2.0.1",
|
||||||
|
"readable-stream": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"version": "0.10.4",
|
"version": "0.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||||
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
|
"integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "2.0.3"
|
"inherits": "2.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
"crypto-js": "3.1.9-1",
|
"crypto-js": "3.1.9-1",
|
||||||
"dayjs": "1.8.20",
|
"dayjs": "1.8.20",
|
||||||
"ecurve": "1.0.6",
|
"ecurve": "1.0.6",
|
||||||
"electrum-client": "git+https://github.com/BlueWallet/rn-electrum-client.git#d194ff69195ccc86f72088ea3712179b4be9cbb4",
|
"electrum-client": "git+https://github.com/BlueWallet/rn-electrum-client.git#aa73cd8bb3f2d6aefd7c054cb08d5bf5151d1cbb",
|
||||||
"eslint-config-prettier": "6.10.0",
|
"eslint-config-prettier": "6.10.0",
|
||||||
"eslint-config-standard": "12.0.0",
|
"eslint-config-standard": "12.0.0",
|
||||||
"eslint-config-standard-react": "7.0.2",
|
"eslint-config-standard-react": "7.0.2",
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
"react-native-snap-carousel": "3.8.4",
|
"react-native-snap-carousel": "3.8.4",
|
||||||
"react-native-sortable-list": "0.0.23",
|
"react-native-sortable-list": "0.0.23",
|
||||||
"react-native-svg": "9.13.6",
|
"react-native-svg": "9.13.6",
|
||||||
"react-native-tcp": "git+https://github.com/aprock/react-native-tcp.git",
|
"react-native-tcp": "git+https://github.com/BlueWallet/react-native-tcp.git",
|
||||||
"react-native-tooltip": "git+https://github.com/marcosrdz/react-native-tooltip.git",
|
"react-native-tooltip": "git+https://github.com/marcosrdz/react-native-tooltip.git",
|
||||||
"react-native-vector-icons": "6.6.0",
|
"react-native-vector-icons": "6.6.0",
|
||||||
"react-native-watch-connectivity": "0.4.2",
|
"react-native-watch-connectivity": "0.4.2",
|
||||||
|
|
|
@ -25,11 +25,13 @@ export default class ElectrumSettings extends Component {
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST);
|
let host = await AsyncStorage.getItem(AppStorage.ELECTRUM_HOST);
|
||||||
let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT);
|
let port = await AsyncStorage.getItem(AppStorage.ELECTRUM_TCP_PORT);
|
||||||
|
let sslPort = await AsyncStorage.getItem(AppStorage.ELECTRUM_SSL_PORT);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
host,
|
host,
|
||||||
port,
|
port,
|
||||||
|
sslPort,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.setState({
|
await this.setState({
|
||||||
|
@ -41,16 +43,19 @@ export default class ElectrumSettings extends Component {
|
||||||
this.setState({ isLoading: true }, async () => {
|
this.setState({ isLoading: true }, async () => {
|
||||||
this.state.host = this.state.host ? this.state.host : '';
|
this.state.host = this.state.host ? this.state.host : '';
|
||||||
this.state.port = this.state.port ? this.state.port : '';
|
this.state.port = this.state.port ? this.state.port : '';
|
||||||
|
this.state.sslPort = this.state.sslPort ? this.state.sslPort : '';
|
||||||
try {
|
try {
|
||||||
if (!this.state.host && !this.state.port) {
|
if (!this.state.host && !this.state.port && !this.state.sslPort) {
|
||||||
await AsyncStorage.setItem(AppStorage.ELECTRUM_HOST, '');
|
await AsyncStorage.setItem(AppStorage.ELECTRUM_HOST, '');
|
||||||
await AsyncStorage.setItem(AppStorage.ELECTRUM_TCP_PORT, '');
|
await AsyncStorage.setItem(AppStorage.ELECTRUM_TCP_PORT, '');
|
||||||
|
await AsyncStorage.setItem(AppStorage.ELECTRUM_SSL_PORT, '');
|
||||||
alert('Your changes have been saved successfully. Restart may be required for changes to take effect.');
|
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))) {
|
} else if (!(await BlueElectrum.testConnection(this.state.host, this.state.port, this.state.sslPort))) {
|
||||||
alert("Can't connect to provided Electrum server");
|
alert("Can't connect to provided Electrum server");
|
||||||
} else {
|
} else {
|
||||||
await AsyncStorage.setItem(AppStorage.ELECTRUM_HOST, this.state.host);
|
await AsyncStorage.setItem(AppStorage.ELECTRUM_HOST, this.state.host);
|
||||||
await AsyncStorage.setItem(AppStorage.ELECTRUM_TCP_PORT, this.state.port);
|
await AsyncStorage.setItem(AppStorage.ELECTRUM_TCP_PORT, this.state.port);
|
||||||
|
await AsyncStorage.setItem(AppStorage.ELECTRUM_SSL_PORT, this.state.sslPort);
|
||||||
alert('Your changes have been saved successfully. Restart may be required for changes to take effect.');
|
alert('Your changes have been saved successfully. Restart may be required for changes to take effect.');
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
@ -99,6 +104,7 @@ export default class ElectrumSettings extends Component {
|
||||||
borderBottomWidth: 0.5,
|
borderBottomWidth: 0.5,
|
||||||
backgroundColor: '#f5f5f5',
|
backgroundColor: '#f5f5f5',
|
||||||
minHeight: 44,
|
minHeight: 44,
|
||||||
|
width: 200,
|
||||||
height: 44,
|
height: 44,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
|
@ -114,6 +120,32 @@ export default class ElectrumSettings extends Component {
|
||||||
underlineColorAndroid="transparent"
|
underlineColorAndroid="transparent"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
<BlueSpacing20 />
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
borderColor: '#d2d2d2',
|
||||||
|
borderBottomColor: '#d2d2d2',
|
||||||
|
borderWidth: 1.0,
|
||||||
|
borderBottomWidth: 0.5,
|
||||||
|
backgroundColor: '#f5f5f5',
|
||||||
|
minHeight: 44,
|
||||||
|
height: 44,
|
||||||
|
width: 200,
|
||||||
|
alignItems: 'center',
|
||||||
|
borderRadius: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
placeholder={'SSL port, usually 50002'}
|
||||||
|
value={this.state.sslPort}
|
||||||
|
onChangeText={text => this.setState({ sslPort: text })}
|
||||||
|
numberOfLines={1}
|
||||||
|
style={{ flex: 1, marginHorizontal: 8, minHeight: 36, height: 36 }}
|
||||||
|
editable={!this.state.isLoading}
|
||||||
|
underlineColorAndroid="transparent"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
<BlueSpacing20 />
|
<BlueSpacing20 />
|
||||||
{this.state.isLoading ? <BlueLoading /> : <BlueButton onPress={this.save} title={loc.settings.save} />}
|
{this.state.isLoading ? <BlueLoading /> : <BlueButton onPress={this.save} title={loc.settings.save} />}
|
||||||
|
|
4
shim.js
4
shim.js
|
@ -1,5 +1,4 @@
|
||||||
/* global __DEV__, localStorage */
|
/* global __DEV__, localStorage */
|
||||||
global.net = require('react-native-tcp');
|
|
||||||
if (typeof __dirname === 'undefined') global.__dirname = '/';
|
if (typeof __dirname === 'undefined') global.__dirname = '/';
|
||||||
if (typeof __filename === 'undefined') global.__filename = '';
|
if (typeof __filename === 'undefined') global.__filename = '';
|
||||||
if (typeof process === 'undefined') {
|
if (typeof process === 'undefined') {
|
||||||
|
@ -16,6 +15,9 @@ if (typeof process === 'undefined') {
|
||||||
process.browser = false;
|
process.browser = false;
|
||||||
if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer;
|
if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer;
|
||||||
|
|
||||||
|
global.net = require('react-native-tcp');
|
||||||
|
global.tls = require('react-native-tcp/tls');
|
||||||
|
|
||||||
// global.location = global.location || { port: 80 }
|
// global.location = global.location || { port: 80 }
|
||||||
const isDev = typeof __DEV__ === 'boolean' && __DEV__;
|
const isDev = typeof __DEV__ === 'boolean' && __DEV__;
|
||||||
process.env['NODE_ENV'] = isDev ? 'development' : 'production';
|
process.env['NODE_ENV'] = isDev ? 'development' : 'production';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* global it, describe, afterAll, beforeAll, jasmine */
|
/* global it, describe, afterAll, beforeAll, jasmine */
|
||||||
const bitcoin = require('bitcoinjs-lib');
|
|
||||||
global.net = require('net');
|
global.net = require('net');
|
||||||
|
global.tls = require('tls');
|
||||||
let BlueElectrum = require('../../BlueElectrum');
|
let BlueElectrum = require('../../BlueElectrum');
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000;
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000;
|
||||||
|
@ -8,7 +8,6 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000;
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
// after all tests we close socket so the test suite can actually terminate
|
// after all tests we close socket so the test suite can actually terminate
|
||||||
BlueElectrum.forceDisconnect();
|
BlueElectrum.forceDisconnect();
|
||||||
return new Promise(resolve => setTimeout(resolve, 10000)); // simple sleep to wait for all timeouts termination
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
@ -22,53 +21,16 @@ beforeAll(async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Electrum', () => {
|
describe('BlueElectrum', () => {
|
||||||
it('ElectrumClient can test connection', async () => {
|
it('ElectrumClient can test connection', async () => {
|
||||||
assert.ok(await BlueElectrum.testConnection('electrum1.bluewallet.io', '50001'));
|
assert.ok(await BlueElectrum.testConnection('electrum1.bluewallet.io', '50001'));
|
||||||
|
assert.ok(await BlueElectrum.testConnection('electrum1.bluewallet.io', false, 443));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ElectrumClient can estimate fees', async () => {
|
it('ElectrumClient can estimate fees', async () => {
|
||||||
assert.ok((await BlueElectrum.estimateFee(1)) > 1);
|
assert.ok((await BlueElectrum.estimateFee(1)) > 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
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');
|
|
||||||
|
|
||||||
try {
|
|
||||||
await mainClient.connect();
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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');
|
|
||||||
assert.ok(balance.confirmed > 0);
|
|
||||||
|
|
||||||
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'));
|
|
||||||
|
|
||||||
// let peers = await mainClient.serverPeers_subscribe();
|
|
||||||
// console.log(peers);
|
|
||||||
mainClient.reconnect = mainClient.keepAlive = () => {}; // dirty hack to make it stop reconnecting
|
|
||||||
mainClient.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('BlueElectrum can do getBalanceByAddress()', async function() {
|
it('BlueElectrum can do getBalanceByAddress()', async function() {
|
||||||
let address = '3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK';
|
let address = '3GCvDBAktgQQtsbN6x5DYiQCMmgZ9Yk8BK';
|
||||||
let balance = await BlueElectrum.getBalanceByAddress(address);
|
let balance = await BlueElectrum.getBalanceByAddress(address);
|
55
tests/integration/ElectrumClient.test.js
Normal file
55
tests/integration/ElectrumClient.test.js
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* global it, describe, jasmine */
|
||||||
|
const bitcoin = require('bitcoinjs-lib');
|
||||||
|
global.net = require('net');
|
||||||
|
global.tls = require('tls');
|
||||||
|
|
||||||
|
let assert = require('assert');
|
||||||
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000;
|
||||||
|
|
||||||
|
const hardcodedPeers = [
|
||||||
|
{ host: 'electrum1.bluewallet.io', ssl: '443' },
|
||||||
|
{ host: 'electrum2.bluewallet.io', ssl: '443' },
|
||||||
|
{ host: 'electrum3.bluewallet.io', ssl: '443' },
|
||||||
|
{ host: 'electrum1.bluewallet.io', tcp: '50001' },
|
||||||
|
{ host: 'electrum2.bluewallet.io', tcp: '50001' },
|
||||||
|
{ host: 'electrum3.bluewallet.io', tcp: '50001' },
|
||||||
|
];
|
||||||
|
|
||||||
|
describe('ElectrumClient', () => {
|
||||||
|
it('can connect and query', async () => {
|
||||||
|
const ElectrumClient = require('electrum-client');
|
||||||
|
|
||||||
|
for (let peer of hardcodedPeers) {
|
||||||
|
let mainClient = new ElectrumClient(peer.ssl || peer.tcp, peer.host, peer.ssl ? 'tls' : 'tcp');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mainClient.connect();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
end - start > 1000 && console.warn(peer.host, 'took', (end - start) / 1000, 'seconds to fetch balance');
|
||||||
|
assert.ok(balance.confirmed > 0);
|
||||||
|
|
||||||
|
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'));
|
||||||
|
|
||||||
|
// let peers = await mainClient.serverPeers_subscribe();
|
||||||
|
// console.log(peers);
|
||||||
|
mainClient.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -12,6 +12,7 @@ const bitcoin = require('bitcoinjs-lib');
|
||||||
global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment
|
global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
|
global.tls = require('tls'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP
|
let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP
|
||||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000;
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { LegacyWallet, SegwitP2SHWallet, SegwitBech32Wallet } from '../../class';
|
import { LegacyWallet, SegwitP2SHWallet, SegwitBech32Wallet } from '../../class';
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
|
global.tls = require('tls'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP
|
let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP
|
||||||
|
|
||||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { WatchOnlyWallet } from '../../class';
|
import { WatchOnlyWallet } from '../../class';
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
|
global.tls = require('tls'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP
|
let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|
|
@ -4,6 +4,7 @@ const bitcoin = require('bitcoinjs-lib');
|
||||||
global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment
|
global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
|
global.tls = require('tls'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
let BlueElectrum = require('../../BlueElectrum');
|
let BlueElectrum = require('../../BlueElectrum');
|
||||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000;
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { HDSegwitBech32Wallet } from '../../class';
|
||||||
global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment
|
global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, but not in RN environment
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
|
global.tls = require('tls'); // needed by Electrum client. For RN it is proviced in shim.js
|
||||||
let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP
|
let BlueElectrum = require('../../BlueElectrum'); // so it connects ASAP
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue