mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-21 22:58:49 +00:00
add mutex to libepiccash
This commit is contained in:
parent
bde7af7b45
commit
4632659e21
1 changed files with 191 additions and 170 deletions
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in a new issue