Skip to content

Commit 7217dff

Browse files
authored
Feat/update electrum server list (#195)
* feat: update Electrum server list and improve testing scripts * feat: update axios and react-native-reanimated versions
1 parent 4557894 commit 7217dff

7 files changed

Lines changed: 136 additions & 53 deletions

File tree

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
"test:ci": "pnpm run test --coverage",
3939
"test:watch": "pnpm run test --watch",
4040
"install-maestro": "curl -Ls 'https://get.maestro.mobile.dev' | bash",
41-
"e2e-test": "maestro test .maestro/ -e APP_ID=com.grimm.labs.app.development"
41+
"e2e-test": "maestro test .maestro/ -e APP_ID=com.grimm.labs.app.development",
42+
"test:electrum-servers": "python3 scripts/test_electrum_servers.py"
4243
},
4344
"dependencies": {
4445
"@breeztech/breez-sdk-spark-react-native": "^0.7.10",
@@ -49,7 +50,7 @@
4950
"@shopify/flash-list": "1.7.6",
5051
"@tanstack/react-query": "^5.52.1",
5152
"app-icon-badge": "^0.1.2",
52-
"axios": "^1.13.5",
53+
"axios": "^1.15.0",
5354
"bdk-rn": "https://github.com/grimm-labs/bdk-rn.git#730e160cb56b739ed0d86f32e939aa064d4f718d",
5455
"bignumber.js": "^9.1.2",
5556
"expo": "~53.0.27",
@@ -89,7 +90,7 @@
8990
"react-native-keyboard-controller": "^1.17.3",
9091
"react-native-otp-entry": "^1.8.4",
9192
"react-native-qrcode-svg": "^6.3.15",
92-
"react-native-reanimated": "~3.19.5",
93+
"react-native-reanimated": "~3.17.4",
9394
"react-native-restart": "0.0.27",
9495
"react-native-safe-area-context": "5.4.0",
9596
"react-native-screens": "^4.11.1",

pnpm-lock.yaml

Lines changed: 33 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/test_electrum_servers.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
2+
# This script tests a list of Electrum servers by attempting to connect to them using SSL.
3+
# It sends a simple Electrum JSON-RPC request (server.version) and checks if a valid response is received.
4+
# If the connection or SSL handshake fails, it prints the error.
5+
#
6+
# If you see the error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:1007)
7+
# It means the server is using a self-signed SSL certificate, which is not trusted by your system's CA store.
8+
# This is a security feature in Python's ssl module to prevent man-in-the-middle attacks.
9+
#
10+
# To connect anyway (not recommended for production), you could disable certificate verification,
11+
# but this exposes you to security risks. Only do this for testing with servers you trust.
12+
#
13+
# Example of disabling verification (uncomment and use at your own risk):
14+
# context = ssl._create_unverified_context()
15+
16+
import socket
17+
import ssl
18+
import sys
19+
from typing import List, Tuple
20+
21+
# Mainnet Electrum servers (name, host, port)
22+
MAINNET_SERVERS: List[Tuple[str, str, int]] = [
23+
("blockstream.info", "blockstream.info", 700),
24+
("electrum.blockstream.info", "electrum.blockstream.info", 50002),
25+
("bitcoin.lu.ke", "bitcoin.lu.ke", 50002),
26+
("electrum.emzy.de", "electrum.emzy.de", 50002),
27+
("electrum.bitaroo.net", "electrum.bitaroo.net", 50002),
28+
("electrum.diynodes.com", "electrum.diynodes.com", 50022),
29+
("fulcrum.sethforprivacy.com", "fulcrum.sethforprivacy.com", 50002),
30+
]
31+
32+
# Testnet Electrum servers (name, host, port)
33+
TESTNET_SERVERS: List[Tuple[str, str, int]] = [
34+
("testnet.aranguren.org", "testnet.aranguren.org", 51002),
35+
("testnet.qtornado.com", "testnet.qtornado.com", 51002),
36+
]
37+
38+
def test_electrum_server(host: str, port: int, timeout: float = 5.0, verify_cert: bool = True) -> bool:
39+
"""
40+
Try to connect to an Electrum server using SSL.
41+
Returns True if the connection and handshake succeed and a valid response is received, False otherwise.
42+
If verify_cert is False, self-signed certificates are accepted (not secure for production).
43+
"""
44+
if verify_cert:
45+
context = ssl.create_default_context()
46+
else:
47+
context = ssl._create_unverified_context()
48+
try:
49+
with socket.create_connection((host, port), timeout=timeout) as sock:
50+
with context.wrap_socket(sock, server_hostname=host) as ssock:
51+
# Send a simple Electrum request (server.version)
52+
ssock.sendall(b'{"id": 0, "method": "server.version", "params": ["electrum-client", "1.4"]}\n')
53+
response = ssock.recv(4096)
54+
if b'server.version' in response or b'result' in response:
55+
return True
56+
except Exception as e:
57+
print(f"Error with {host}:{port} - {e}")
58+
return False
59+
60+
61+
def main():
62+
import argparse
63+
parser = argparse.ArgumentParser(description="Test Electrum servers (mainnet and testnet)")
64+
parser.add_argument('--no-verify-cert', action='store_true', help='Disable SSL certificate verification (accept self-signed certs)')
65+
args = parser.parse_args()
66+
verify_cert = not args.no_verify_cert
67+
68+
print("\nTesting Mainnet Electrum servers:")
69+
for name, host, port in MAINNET_SERVERS:
70+
print(f"Testing {name} ({host}:{port})...", end=" ")
71+
if test_electrum_server(host, port, verify_cert=verify_cert):
72+
print("OK")
73+
else:
74+
print("FAILED")
75+
76+
print("\nTesting Testnet Electrum servers:")
77+
for name, host, port in TESTNET_SERVERS:
78+
print(f"Testing {name} ({host}:{port})...", end=" ")
79+
if test_electrum_server(host, port, verify_cert=verify_cert):
80+
print("OK")
81+
else:
82+
print("FAILED")
83+
84+
if __name__ == "__main__":
85+
main()

src/app/(app)/_layout.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ const TabLayout = () => {
7171
}, []);
7272

7373
useEffect(() => {
74-
console.log('Data loaded:', isDataLoaded, 'Has seed phrase:', hasSeedPhrase, 'Breez initialized:', isBreezInitialized, 'BDK initialized:', isBdkInitialized);
7574
if (isDataLoaded && hasSeedPhrase && (!isBreezInitialized || !isBdkInitialized)) {
7675
initializeBreez();
7776
initializeBdk();

src/lib/constant.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,21 @@ export const MEMPOOL_SSL_URL = 'ssl://electrum.blockstream.info:60002';
44
export const DEFAULT_PORTS = { t: '50001', s: '50002' } as const;
55
export const DEFAULT_PORTS_TESTNET = { t: '51001', s: '51002' } as const;
66

7+
// Electrum mainnet servers (SSL only)
78
export const DEFAULT_SERVERS = {
8-
'blockstream.info': { s: '700', t: '110' },
9+
'blockstream.info': { s: '700' },
10+
'electrum.blockstream.info': { s: '50002' },
11+
'electrum.diynodes.com': { s: '50022' },
12+
// 'bitcoin.lu.ke': { s: '50002' },
13+
// 'electrum.emzy.de': { s: '50002' },
14+
// 'electrum.bitaroo.net': { s: '50002' },
15+
// 'fulcrum.sethforprivacy.com': { s: '50002' },
916
} as const;
1017

18+
// Electrum testnet servers (SSL only)
1119
export const DEFAULT_SERVERS_TESTNET = {
12-
'blockstream.info': { s: '993', t: '143' },
13-
'electrum.blockstream.info': { s: '60002', t: '60001' },
20+
'testnet.aranguren.org': { s: '51002' },
21+
'testnet.qtornado.com': { s: '51002' },
1422
} as const;
1523

1624
export const GRIMM_APP_LN_URL_DOMAIN = 'pay.usegrimm.app';

src/lib/context/bdk-context.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,14 @@ export const BdkProvider: React.FC<BdkProviderProps> = ({ children }) => {
264264
electrumUrl = `ssl://${host}:${port}`;
265265
}
266266

267+
const isTestnet = getOnchainNetwork() !== Network.Bitcoin;
267268
const blockchainConfig = {
268269
url: electrumUrl,
269270
sock5: null,
270271
retry: 5,
271272
timeout: 10,
272273
stopGap: 100,
273-
validateDomain: true,
274+
validateDomain: !isTestnet, // Disable certificate validation only for testnet
274275
};
275276

276277
let blockchain;

src/lib/context/breez-context.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ class BreezEventListener implements EventListener {
146146
async onEvent(event: SdkEvent): Promise<void> {
147147
switch (event.tag) {
148148
case SdkEvent_Tags.PaymentSucceeded:
149-
console.log('Payment succeeded:', event);
150149
this.onPaymentSucceeded(event);
151150
break;
152151
case SdkEvent_Tags.PaymentFailed:
@@ -512,7 +511,7 @@ export const BreezProvider: React.FC<BreezProviderProps> = ({ children }) => {
512511
}, SYNC_INTERVAL);
513512

514513
return () => {
515-
console.log('Stopping automatic synchronization');
514+
console.debug('Stopping automatic synchronization');
516515
clearInterval(syncInterval);
517516
};
518517
}, [refreshWalletInfo]);

0 commit comments

Comments
 (0)