mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
Merge pull request #357 from cypherstack/epicbox-failover
Epicbox failover - When epicbox server is down default to EU server
This commit is contained in:
commit
6ac856d31b
4 changed files with 606 additions and 326 deletions
|
@ -6,7 +6,6 @@ import 'dart:isolate';
|
||||||
import 'package:decimal/decimal.dart';
|
import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_libepiccash/epic_cash.dart';
|
import 'package:flutter_libepiccash/epic_cash.dart';
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:stack_wallet_backup/generate_password.dart';
|
import 'package:stack_wallet_backup/generate_password.dart';
|
||||||
|
@ -37,6 +36,7 @@ import 'package:stackwallet/utilities/prefs.dart';
|
||||||
import 'package:stackwallet/utilities/stack_file_system.dart';
|
import 'package:stackwallet/utilities/stack_file_system.dart';
|
||||||
import 'package:stackwallet/utilities/test_epic_box_connection.dart';
|
import 'package:stackwallet/utilities/test_epic_box_connection.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
import 'package:websocket_universal/websocket_universal.dart';
|
||||||
|
|
||||||
const int MINIMUM_CONFIRMATIONS = 10;
|
const int MINIMUM_CONFIRMATIONS = 10;
|
||||||
|
|
||||||
|
@ -462,6 +462,18 @@ class EpicCashWallet extends CoinServiceAPI
|
||||||
dynamic message;
|
dynamic message;
|
||||||
|
|
||||||
String receiverAddress = txData['addresss'] as String;
|
String receiverAddress = txData['addresss'] as String;
|
||||||
|
|
||||||
|
if (!receiverAddress.startsWith("http://") ||
|
||||||
|
!receiverAddress.startsWith("https://")) {
|
||||||
|
final decoded = json.decode(epicboxConfig);
|
||||||
|
bool isEpicboxConnected = await testEpicboxServer(
|
||||||
|
decoded["epicbox_domain"] as String,
|
||||||
|
decoded["epicbox_port"] as int);
|
||||||
|
if (!isEpicboxConnected) {
|
||||||
|
throw Exception("Failed to send TX : Unable to reach epicbox server");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await m.protect(() async {
|
await m.protect(() async {
|
||||||
if (receiverAddress.startsWith("http://") ||
|
if (receiverAddress.startsWith("http://") ||
|
||||||
receiverAddress.startsWith("https://")) {
|
receiverAddress.startsWith("https://")) {
|
||||||
|
@ -980,22 +992,75 @@ class EpicCashWallet extends CoinServiceAPI
|
||||||
return stringConfig;
|
return stringConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> testEpicboxServer(String host, int port) async {
|
||||||
|
final websocketConnectionUri = 'wss://$host:$port';
|
||||||
|
const connectionOptions = SocketConnectionOptions(
|
||||||
|
pingIntervalMs: 3000,
|
||||||
|
timeoutConnectionMs: 4000,
|
||||||
|
|
||||||
|
/// see ping/pong messages in [logEventStream] stream
|
||||||
|
skipPingMessages: true,
|
||||||
|
|
||||||
|
/// Set this attribute to `true` if do not need any ping/pong
|
||||||
|
/// messages and ping measurement. Default is `false`
|
||||||
|
pingRestrictionForce: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
final IMessageProcessor<String, String> textSocketProcessor =
|
||||||
|
SocketSimpleTextProcessor();
|
||||||
|
final textSocketHandler = IWebSocketHandler<String, String>.createClient(
|
||||||
|
websocketConnectionUri,
|
||||||
|
textSocketProcessor,
|
||||||
|
connectionOptions: connectionOptions,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Listening to server responses:
|
||||||
|
bool isConnected = true;
|
||||||
|
textSocketHandler.incomingMessagesStream.listen((inMsg) {
|
||||||
|
Logging.instance.log(
|
||||||
|
'> webSocket got text message from server: "$inMsg" '
|
||||||
|
'[ping: ${textSocketHandler.pingDelayMs}]',
|
||||||
|
level: LogLevel.Info);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Connecting to server:
|
||||||
|
final isTextSocketConnected = await textSocketHandler.connect();
|
||||||
|
if (!isTextSocketConnected) {
|
||||||
|
// ignore: avoid_print
|
||||||
|
Logging.instance.log(
|
||||||
|
'Connection to [$websocketConnectionUri] failed for some reason!',
|
||||||
|
level: LogLevel.Error);
|
||||||
|
isConnected = false;
|
||||||
|
}
|
||||||
|
return isConnected;
|
||||||
|
}
|
||||||
|
|
||||||
Future<String> getEpicBoxConfig() async {
|
Future<String> getEpicBoxConfig() async {
|
||||||
final storedConfig =
|
String? storedConfig =
|
||||||
await _secureStore.read(key: '${_walletId}_epicboxConfig');
|
await _secureStore.read(key: '${_walletId}_epicboxConfig');
|
||||||
if (storedConfig != null) {
|
if (storedConfig == null) {
|
||||||
final decoded = json.decode(storedConfig!);
|
return json.encode(DefaultNodes.defaultEpicBoxConfig);
|
||||||
|
} else {
|
||||||
|
dynamic decoded = json.decode(storedConfig!);
|
||||||
final domain = decoded["domain"] ?? "empty";
|
final domain = decoded["domain"] ?? "empty";
|
||||||
if (domain != "empty") {
|
if (domain != "empty") {
|
||||||
//If we have the old invalid config - update
|
//If we have the old invalid config, use the new default one
|
||||||
await _secureStore.write(
|
// new storage format stores domain under "epicbox_domain", old storage format used "domain"
|
||||||
key: '${_walletId}_epicboxConfig',
|
storedConfig = DefaultNodes.defaultEpicBoxConfig;
|
||||||
value: DefaultNodes.defaultEpicBoxConfig);
|
decoded = json.decode(storedConfig);
|
||||||
}
|
}
|
||||||
return await _secureStore.read(key: '${_walletId}_epicboxConfig') ??
|
//Check Epicbox is up before returning it
|
||||||
DefaultNodes.defaultEpicBoxConfig;
|
bool isEpicboxConnected = await testEpicboxServer(
|
||||||
|
decoded["epicbox_domain"] as String, decoded["epicbox_port"] as int);
|
||||||
|
|
||||||
|
if (!isEpicboxConnected) {
|
||||||
|
//Default Epicbox is not connected, Defaulting to Europe
|
||||||
|
storedConfig = json.encode(DefaultNodes.epicBoxConfigEUR);
|
||||||
|
// TODO test this connection before returning it, iterating through the list of default Epic Box servers
|
||||||
|
}
|
||||||
|
|
||||||
|
return storedConfig;
|
||||||
}
|
}
|
||||||
return DefaultNodes.defaultEpicBoxConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getRealConfig() async {
|
Future<String> getRealConfig() async {
|
||||||
|
|
|
@ -262,4 +262,11 @@ abstract class DefaultNodes {
|
||||||
"epicbox_protocol_unsecure": false,
|
"epicbox_protocol_unsecure": false,
|
||||||
"epicbox_address_index": 0,
|
"epicbox_address_index": 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static final String epicBoxConfigEUR = jsonEncode({
|
||||||
|
"epicbox_domain": "epicbox.fastepic.eu",
|
||||||
|
"epicbox_port": 443,
|
||||||
|
"epicbox_protocol_unsecure": false,
|
||||||
|
"epicbox_address_index": 0,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
837
pubspec.lock
837
pubspec.lock
File diff suppressed because it is too large
Load diff
|
@ -21,6 +21,7 @@ dependencies:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
ffi: ^2.0.1
|
ffi: ^2.0.1
|
||||||
mutex: ^3.0.0
|
mutex: ^3.0.0
|
||||||
|
websocket_universal: ^0.5.1
|
||||||
|
|
||||||
lelantus:
|
lelantus:
|
||||||
path: ./crypto_plugins/flutter_liblelantus
|
path: ./crypto_plugins/flutter_liblelantus
|
||||||
|
|
Loading…
Reference in a new issue