add mutex to libepiccash

This commit is contained in:
ryleedavis 2023-10-06 14:28:43 -06:00
parent bde7af7b45
commit 4632659e21

View file

@ -13,6 +13,7 @@ import 'package:stackwallet/models/isar/models/blockchain_data/epic_transaction.
/// ///
abstract class LibEpiccash { abstract class LibEpiccash {
static final Mutex _mutex = Mutex(); static final Mutex _mutex = Mutex();
static final Mutex m = Mutex();
/// ///
/// Check if [address] is a valid epiccash address according to libepiccash /// Check if [address] is a valid epiccash address according to libepiccash
@ -36,6 +37,7 @@ abstract class LibEpiccash {
// TODO: ensure the above documentation comment is correct // TODO: ensure the above documentation comment is correct
// TODO: ensure this will always return the mnemonic. If not, this function should throw an exception // TODO: ensure this will always return the mnemonic. If not, this function should throw an exception
//Function is used in _getMnemonicList() //Function is used in _getMnemonicList()
// wrap in mutex? -> would need to be Future<String>
static String getMnemonic() { static String getMnemonic() {
try { try {
String mnemonic = lib_epiccash.walletMnemonic(); String mnemonic = lib_epiccash.walletMnemonic();
@ -77,19 +79,21 @@ abstract class LibEpiccash {
required String password, required String password,
required String name, required String name,
}) async { }) async {
try { return await m.protect(() async {
return await compute( try {
_initializeWalletWrapper, return await compute(
( _initializeWalletWrapper,
config: config, (
mnemonic: mnemonic, config: config,
password: password, mnemonic: mnemonic,
name: name, password: password,
), name: name,
); ),
} catch (e) { );
throw ("Error creating new wallet : ${e.toString()}"); } catch (e) {
} throw ("Error creating new wallet : ${e.toString()}");
}
});
} }
/// ///
@ -116,34 +120,36 @@ abstract class LibEpiccash {
{required String wallet, {required String wallet,
required int refreshFromNode, required int refreshFromNode,
required int minimumConfirmations}) async { required int minimumConfirmations}) async {
try { return await m.protect(() async {
String balances = await compute(_walletBalancesWrapper, ( try {
wallet: wallet, String balances = await compute(_walletBalancesWrapper, (
refreshFromNode: refreshFromNode, wallet: wallet,
minimumConfirmations: minimumConfirmations, refreshFromNode: refreshFromNode,
)); minimumConfirmations: minimumConfirmations,
));
//If balances is valid json return, else return error //If balances is valid json return, else return error
if (balances.toUpperCase().contains("ERROR")) { if (balances.toUpperCase().contains("ERROR")) {
throw Exception(balances); throw Exception(balances);
}
var jsonBalances = json.decode(balances);
//Return balances as record
({
double spendable,
double pending,
double total,
double awaitingFinalization
}) balancesRecord = (
spendable: jsonBalances['amount_currently_spendable'],
pending: jsonBalances['amount_awaiting_finalization'],
total: jsonBalances['total'],
awaitingFinalization: jsonBalances['amount_awaiting_finalization'],
);
return balancesRecord;
} catch (e) {
throw ("Error getting wallet info : ${e.toString()}");
} }
var jsonBalances = json.decode(balances); });
//Return balances as record
({
double spendable,
double pending,
double total,
double awaitingFinalization
}) balancesRecord = (
spendable: jsonBalances['amount_currently_spendable'],
pending: jsonBalances['amount_awaiting_finalization'],
total: jsonBalances['total'],
awaitingFinalization: jsonBalances['amount_awaiting_finalization'],
);
return balancesRecord;
} catch (e) {
throw ("Error getting wallet info : ${e.toString()}");
}
} }
/// ///
@ -167,15 +173,17 @@ abstract class LibEpiccash {
required int startHeight, required int startHeight,
required int numberOfBlocks, required int numberOfBlocks,
}) async { }) async {
try { return await m.protect(() async {
return await compute(_scanOutputsWrapper, ( try {
wallet: wallet, return await compute(_scanOutputsWrapper, (
startHeight: startHeight, wallet: wallet,
numberOfBlocks: numberOfBlocks, startHeight: startHeight,
)); numberOfBlocks: numberOfBlocks,
} catch (e) { ));
throw ("Error getting scanning outputs : ${e.toString()}"); } catch (e) {
} throw ("Error getting scanning outputs : ${e.toString()}");
}
});
} }
/// ///
@ -214,36 +222,38 @@ abstract class LibEpiccash {
required int minimumConfirmations, required int minimumConfirmations,
required String note, required String note,
}) async { }) async {
try { return await m.protect(() async {
String result = await compute(_createTransactionWrapper, ( try {
wallet: wallet, String result = await compute(_createTransactionWrapper, (
amount: amount, wallet: wallet,
address: address, amount: amount,
secretKeyIndex: secretKeyIndex, address: address,
epicboxConfig: epicboxConfig, secretKeyIndex: secretKeyIndex,
minimumConfirmations: minimumConfirmations, epicboxConfig: epicboxConfig,
note: note, minimumConfirmations: minimumConfirmations,
)); note: note,
));
if (result.toUpperCase().contains("ERROR")) { if (result.toUpperCase().contains("ERROR")) {
throw Exception("Error creating transaction ${result.toString()}"); throw Exception("Error creating transaction ${result.toString()}");
}
//Decode sent tx and return Slate Id
final slate0 = jsonDecode(result);
final slate = jsonDecode(slate0[0] as String);
final part1 = jsonDecode(slate[0] as String);
final part2 = jsonDecode(slate[1] as String);
({String slateId, String commitId}) data = (
slateId: part1[0]['tx_slate_id'],
commitId: part2['tx']['body']['outputs'][0]['commit'],
);
return data;
} catch (e) {
throw ("Error creating epic transaction : ${e.toString()}");
} }
});
//Decode sent tx and return Slate Id
final slate0 = jsonDecode(result);
final slate = jsonDecode(slate0[0] as String);
final part1 = jsonDecode(slate[0] as String);
final part2 = jsonDecode(slate[1] as String);
({String slateId, String commitId}) data = (
slateId: part1[0]['tx_slate_id'],
commitId: part2['tx']['body']['outputs'][0]['commit'],
);
return data;
} catch (e) {
throw ("Error creating epic transaction : ${e.toString()}");
}
} }
/// ///
@ -268,28 +278,31 @@ abstract class LibEpiccash {
required String wallet, required String wallet,
required int refreshFromNode, required int refreshFromNode,
}) async { }) async {
try { return await m.protect(() async {
var result = await compute(_getTransactionsWrapper, ( try {
wallet: wallet, var result = await compute(_getTransactionsWrapper, (
refreshFromNode: refreshFromNode, wallet: wallet,
)); refreshFromNode: refreshFromNode,
));
if (result.toUpperCase().contains("ERROR")) { if (result.toUpperCase().contains("ERROR")) {
throw Exception("Error getting epic transactions ${result.toString()}"); throw Exception(
"Error getting epic transactions ${result.toString()}");
}
//Parse the returned data as an EpicTransaction
List<EpicTransaction> finalResult = [];
var jsonResult = json.decode(result) as List;
for (var tx in jsonResult) {
EpicTransaction itemTx = EpicTransaction.fromJson(tx);
finalResult.add(itemTx);
}
return finalResult;
} catch (e) {
throw ("Error getting epic transactions : ${e.toString()}");
} }
});
//Parse the returned data as an EpicTransaction
List<EpicTransaction> finalResult = [];
var jsonResult = json.decode(result) as List;
for (var tx in jsonResult) {
EpicTransaction itemTx = EpicTransaction.fromJson(tx);
finalResult.add(itemTx);
}
return finalResult;
} catch (e) {
throw ("Error getting epic transactions : ${e.toString()}");
}
} }
/// ///
@ -315,14 +328,16 @@ abstract class LibEpiccash {
required String wallet, required String wallet,
required String transactionId, required String transactionId,
}) async { }) async {
try { return await m.protect(() async {
return await compute(_cancelTransactionWrapper, ( try {
wallet: wallet, return await compute(_cancelTransactionWrapper, (
transactionId: transactionId, wallet: wallet,
)); transactionId: transactionId,
} catch (e) { ));
throw ("Error canceling epic transaction : ${e.toString()}"); } catch (e) {
} throw ("Error canceling epic transaction : ${e.toString()}");
}
});
} }
static Future<int> _chainHeightWrapper( static Future<int> _chainHeightWrapper(
@ -336,11 +351,13 @@ abstract class LibEpiccash {
static Future<int> getChainHeight({ static Future<int> getChainHeight({
required String config, required String config,
}) async { }) async {
try { return await m.protect(() async {
return await compute(_chainHeightWrapper, (config: config,)); try {
} catch (e) { return await compute(_chainHeightWrapper, (config: config,));
throw ("Error getting chain height : ${e.toString()}"); } catch (e) {
} throw ("Error getting chain height : ${e.toString()}");
}
});
} }
/// ///
@ -368,15 +385,17 @@ abstract class LibEpiccash {
required int index, required int index,
required String epicboxConfig, required String epicboxConfig,
}) async { }) async {
try { return await m.protect(() async {
return await compute(_addressInfoWrapper, ( try {
wallet: wallet, return await compute(_addressInfoWrapper, (
index: index, wallet: wallet,
epicboxConfig: epicboxConfig, index: index,
)); epicboxConfig: epicboxConfig,
} catch (e) { ));
throw ("Error getting address info : ${e.toString()}"); } catch (e) {
} throw ("Error getting address info : ${e.toString()}");
}
});
} }
/// ///
@ -406,64 +425,66 @@ abstract class LibEpiccash {
required int minimumConfirmations, required int minimumConfirmations,
required int available, required int available,
}) async { }) async {
try { return await m.protect(() async {
String fees = await compute(_transactionFeesWrapper, ( try {
wallet: wallet, String fees = await compute(_transactionFeesWrapper, (
amount: amount, wallet: wallet,
minimumConfirmations: minimumConfirmations, amount: amount,
)); minimumConfirmations: minimumConfirmations,
));
if (available == amount) { if (available == amount) {
if (fees.contains("Required")) { if (fees.contains("Required")) {
var splits = fees.split(" "); var splits = fees.split(" ");
Decimal required = Decimal.zero; Decimal required = Decimal.zero;
Decimal available = Decimal.zero; Decimal available = Decimal.zero;
for (int i = 0; i < splits.length; i++) { for (int i = 0; i < splits.length; i++) {
var word = splits[i]; var word = splits[i];
if (word == "Required:") { if (word == "Required:") {
required = Decimal.parse(splits[i + 1].replaceAll(",", "")); required = Decimal.parse(splits[i + 1].replaceAll(",", ""));
} else if (word == "Available:") { } else if (word == "Available:") {
available = Decimal.parse(splits[i + 1].replaceAll(",", "")); available = Decimal.parse(splits[i + 1].replaceAll(",", ""));
}
} }
int largestSatoshiFee =
((required - available) * Decimal.fromInt(100000000))
.toBigInt()
.toInt();
var amountSending = amount - largestSatoshiFee;
//Get fees for this new amount
({
String wallet,
int amount,
}) data = (wallet: wallet, amount: amountSending);
fees = await compute(_transactionFeesWrapper, (
wallet: wallet,
amount: amountSending,
minimumConfirmations: minimumConfirmations,
));
} }
int largestSatoshiFee =
((required - available) * Decimal.fromInt(100000000))
.toBigInt()
.toInt();
var amountSending = amount - largestSatoshiFee;
//Get fees for this new amount
({
String wallet,
int amount,
}) data = (wallet: wallet, amount: amountSending);
fees = await compute(_transactionFeesWrapper, (
wallet: wallet,
amount: amountSending,
minimumConfirmations: minimumConfirmations,
));
} }
}
if (fees.toUpperCase().contains("ERROR")) { if (fees.toUpperCase().contains("ERROR")) {
//Check if the error is an //Check if the error is an
//Throw the returned error //Throw the returned error
throw Exception(fees); throw Exception(fees);
}
var decodedFees = json.decode(fees);
var feeItem = decodedFees[0];
({
bool strategyUseAll,
int total,
int fee,
}) feeRecord = (
strategyUseAll: feeItem['selection_strategy_is_use_all'],
total: feeItem['total'],
fee: feeItem['fee'],
);
return feeRecord;
} catch (e) {
throw (e.toString());
} }
var decodedFees = json.decode(fees); });
var feeItem = decodedFees[0];
({
bool strategyUseAll,
int total,
int fee,
}) feeRecord = (
strategyUseAll: feeItem['selection_strategy_is_use_all'],
total: feeItem['total'],
fee: feeItem['fee'],
);
return feeRecord;
} catch (e) {
throw (e.toString());
}
} }
/// ///