mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-05-19 19:14:43 +00:00
send all for private funds in firo, and bug fix for failing to load wallets
This commit is contained in:
parent
2b6aa83535
commit
d672c2bd17
4 changed files with 132 additions and 63 deletions
lib
|
@ -10,6 +10,8 @@ import 'package:stackwallet/models/trade_wallet_lookup.dart';
|
||||||
import 'package:stackwallet/services/wallets_service.dart';
|
import 'package:stackwallet/services/wallets_service.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
|
||||||
|
import 'package:stackwallet/utilities/logger.dart';
|
||||||
|
|
||||||
class DB {
|
class DB {
|
||||||
static const String boxNameAddressBook = "addressBook";
|
static const String boxNameAddressBook = "addressBook";
|
||||||
static const String boxNameDebugInfo = "debugInfoBox";
|
static const String boxNameDebugInfo = "debugInfoBox";
|
||||||
|
@ -141,6 +143,18 @@ class DB {
|
||||||
|
|
||||||
Future<void> _loadWalletBoxes() async {
|
Future<void> _loadWalletBoxes() async {
|
||||||
final names = _boxAllWalletsData.get("names") as Map? ?? {};
|
final names = _boxAllWalletsData.get("names") as Map? ?? {};
|
||||||
|
names.removeWhere((name, dyn) {
|
||||||
|
final jsonObject = Map<String, dynamic>.from(dyn as Map);
|
||||||
|
try {
|
||||||
|
Coin.values.byName(jsonObject["coin"] as String);
|
||||||
|
return false;
|
||||||
|
} catch (e, s) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"Error, ${jsonObject["coin"]} does not exist, $name wallet cannot be loaded",
|
||||||
|
level: LogLevel.Error);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
final mapped = Map<String, dynamic>.from(names).map((name, dyn) => MapEntry(
|
final mapped = Map<String, dynamic>.from(names).map((name, dyn) => MapEntry(
|
||||||
name, WalletInfo.fromJson(Map<String, dynamic>.from(dyn as Map))));
|
name, WalletInfo.fromJson(Map<String, dynamic>.from(dyn as Map))));
|
||||||
|
|
||||||
|
|
|
@ -731,6 +731,38 @@ Future<void> _setTestnetWrapper(bool isTestnet) async {
|
||||||
// setTestnet(isTestnet);
|
// setTestnet(isTestnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> getAnonymity(int groupID) async {
|
||||||
|
Logging.instance.log("getAnonymity", level: LogLevel.Info);
|
||||||
|
final Client client = Client();
|
||||||
|
try {
|
||||||
|
final uri = Uri.parse("$kStackCommunityNodesEndpoint/getAnonymity");
|
||||||
|
|
||||||
|
final anonSetResult = await client.post(
|
||||||
|
uri,
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: jsonEncode({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": "0",
|
||||||
|
'index': groupID,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: should the following be removed for security reasons in production?
|
||||||
|
Logging.instance
|
||||||
|
.log(anonSetResult.statusCode.toString(), level: LogLevel.Info);
|
||||||
|
Logging.instance.log(anonSetResult.body.toString(), level: LogLevel.Info);
|
||||||
|
final response = jsonDecode(anonSetResult.body.toString());
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e, s) {
|
||||||
|
Logging.instance.log("$e $s", level: LogLevel.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Handles a single instance of a firo wallet
|
/// Handles a single instance of a firo wallet
|
||||||
class FiroWallet extends CoinServiceAPI {
|
class FiroWallet extends CoinServiceAPI {
|
||||||
static const integrationTestFlag =
|
static const integrationTestFlag =
|
||||||
|
@ -1087,8 +1119,16 @@ class FiroWallet extends CoinServiceAPI {
|
||||||
Map<String, dynamic>? args,
|
Map<String, dynamic>? args,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
|
// check for send all
|
||||||
|
bool isSendAll = false;
|
||||||
|
final balance =
|
||||||
|
Format.decimalAmountToSatoshis(await availablePrivateBalance());
|
||||||
|
if (satoshiAmount == balance) {
|
||||||
|
print("is send all");
|
||||||
|
isSendAll = true;
|
||||||
|
}
|
||||||
dynamic txHexOrError =
|
dynamic txHexOrError =
|
||||||
await _createJoinSplitTransaction(satoshiAmount, address, false);
|
await _createJoinSplitTransaction(satoshiAmount, address, isSendAll);
|
||||||
Logging.instance.log("txHexOrError $txHexOrError", level: LogLevel.Error);
|
Logging.instance.log("txHexOrError $txHexOrError", level: LogLevel.Error);
|
||||||
if (txHexOrError is int) {
|
if (txHexOrError is int) {
|
||||||
// Here, we assume that transaction crafting returned an error
|
// Here, we assume that transaction crafting returned an error
|
||||||
|
|
|
@ -103,75 +103,79 @@ class NotificationsService extends ChangeNotifier {
|
||||||
|
|
||||||
void _checkTransactions() async {
|
void _checkTransactions() async {
|
||||||
for (final notification in _watchedTransactionNotifications) {
|
for (final notification in _watchedTransactionNotifications) {
|
||||||
final Coin coin = coinFromPrettyName(notification.coinName);
|
try {
|
||||||
final txid = notification.txid!;
|
final Coin coin = coinFromPrettyName(notification.coinName);
|
||||||
|
final txid = notification.txid!;
|
||||||
|
|
||||||
final node = nodeService.getPrimaryNodeFor(coin: coin);
|
final node = nodeService.getPrimaryNodeFor(coin: coin);
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
if (coin.isElectrumXCoin) {
|
if (coin.isElectrumXCoin) {
|
||||||
final eNode = ElectrumXNode(
|
final eNode = ElectrumXNode(
|
||||||
address: node.host,
|
address: node.host,
|
||||||
port: node.port,
|
port: node.port,
|
||||||
name: node.name,
|
name: node.name,
|
||||||
id: node.id,
|
id: node.id,
|
||||||
useSSL: node.useSSL,
|
useSSL: node.useSSL,
|
||||||
);
|
|
||||||
final failovers = nodeService
|
|
||||||
.failoverNodesFor(coin: coin)
|
|
||||||
.map((e) => ElectrumXNode(
|
|
||||||
address: e.host,
|
|
||||||
port: e.port,
|
|
||||||
name: e.name,
|
|
||||||
id: e.id,
|
|
||||||
useSSL: e.useSSL,
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
final client = ElectrumX.from(
|
|
||||||
node: eNode,
|
|
||||||
failovers: failovers,
|
|
||||||
prefs: prefs,
|
|
||||||
);
|
|
||||||
final tx = await client.getTransaction(txHash: txid);
|
|
||||||
|
|
||||||
int confirmations = tx["confirmations"] as int? ?? 0;
|
|
||||||
|
|
||||||
bool shouldWatchForUpdates = true;
|
|
||||||
// check if the number of confirmations is greater than the number
|
|
||||||
// required by the wallet to count the tx as confirmed and update the
|
|
||||||
// flag on whether this notification should still be monitored
|
|
||||||
if (confirmations >= coin.requiredConfirmations) {
|
|
||||||
shouldWatchForUpdates = false;
|
|
||||||
confirmations = coin.requiredConfirmations;
|
|
||||||
}
|
|
||||||
|
|
||||||
// grab confirms string to compare
|
|
||||||
final String newConfirms =
|
|
||||||
"($confirmations/${coin.requiredConfirmations})";
|
|
||||||
final String oldConfirms =
|
|
||||||
notification.title.substring(notification.title.lastIndexOf("("));
|
|
||||||
|
|
||||||
// only update if they don't match
|
|
||||||
if (oldConfirms != newConfirms) {
|
|
||||||
final String newTitle =
|
|
||||||
notification.title.replaceFirst(oldConfirms, newConfirms);
|
|
||||||
|
|
||||||
final updatedNotification = notification.copyWith(
|
|
||||||
title: newTitle,
|
|
||||||
shouldWatchForUpdates: shouldWatchForUpdates,
|
|
||||||
);
|
);
|
||||||
|
final failovers = nodeService
|
||||||
|
.failoverNodesFor(coin: coin)
|
||||||
|
.map((e) => ElectrumXNode(
|
||||||
|
address: e.host,
|
||||||
|
port: e.port,
|
||||||
|
name: e.name,
|
||||||
|
id: e.id,
|
||||||
|
useSSL: e.useSSL,
|
||||||
|
))
|
||||||
|
.toList();
|
||||||
|
|
||||||
// remove from watch list if shouldWatchForUpdates was changed
|
final client = ElectrumX.from(
|
||||||
if (!shouldWatchForUpdates) {
|
node: eNode,
|
||||||
await _deleteWatchedTxNotification(notification);
|
failovers: failovers,
|
||||||
|
prefs: prefs,
|
||||||
|
);
|
||||||
|
final tx = await client.getTransaction(txHash: txid);
|
||||||
|
|
||||||
|
int confirmations = tx["confirmations"] as int? ?? 0;
|
||||||
|
|
||||||
|
bool shouldWatchForUpdates = true;
|
||||||
|
// check if the number of confirmations is greater than the number
|
||||||
|
// required by the wallet to count the tx as confirmed and update the
|
||||||
|
// flag on whether this notification should still be monitored
|
||||||
|
if (confirmations >= coin.requiredConfirmations) {
|
||||||
|
shouldWatchForUpdates = false;
|
||||||
|
confirmations = coin.requiredConfirmations;
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaces the current notification with the updated one
|
// grab confirms string to compare
|
||||||
add(updatedNotification, true);
|
final String newConfirms =
|
||||||
|
"($confirmations/${coin.requiredConfirmations})";
|
||||||
|
final String oldConfirms = notification.title
|
||||||
|
.substring(notification.title.lastIndexOf("("));
|
||||||
|
|
||||||
|
// only update if they don't match
|
||||||
|
if (oldConfirms != newConfirms) {
|
||||||
|
final String newTitle =
|
||||||
|
notification.title.replaceFirst(oldConfirms, newConfirms);
|
||||||
|
|
||||||
|
final updatedNotification = notification.copyWith(
|
||||||
|
title: newTitle,
|
||||||
|
shouldWatchForUpdates: shouldWatchForUpdates,
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove from watch list if shouldWatchForUpdates was changed
|
||||||
|
if (!shouldWatchForUpdates) {
|
||||||
|
await _deleteWatchedTxNotification(notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaces the current notification with the updated one
|
||||||
|
add(updatedNotification, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO: check non electrumx coins
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// TODO: check non electrumx coins
|
|
||||||
}
|
}
|
||||||
|
} catch (e, s) {
|
||||||
|
Logging.instance.log("$e $s", level: LogLevel.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,17 @@ class WalletsService extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
Logging.instance.log("Fetched wallet names: $names", level: LogLevel.Info);
|
Logging.instance.log("Fetched wallet names: $names", level: LogLevel.Info);
|
||||||
final mapped = Map<String, dynamic>.from(names);
|
final mapped = Map<String, dynamic>.from(names);
|
||||||
|
mapped.removeWhere((name, dyn) {
|
||||||
|
final jsonObject = Map<String, dynamic>.from(dyn as Map);
|
||||||
|
try {
|
||||||
|
Coin.values.byName(jsonObject["coin"] as String);
|
||||||
|
return false;
|
||||||
|
} catch (e, s) {
|
||||||
|
Logging.instance.log("Error, ${jsonObject["coin"]} does not exist",
|
||||||
|
level: LogLevel.Error);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return mapped.map((name, dyn) => MapEntry(
|
return mapped.map((name, dyn) => MapEntry(
|
||||||
name, WalletInfo.fromJson(Map<String, dynamic>.from(dyn as Map))));
|
name, WalletInfo.fromJson(Map<String, dynamic>.from(dyn as Map))));
|
||||||
|
|
Loading…
Reference in a new issue