Merge pull request #26 from cypherstack/open-wallet-and-store

Open wallet and store
This commit is contained in:
julian-CStack 2022-09-01 16:20:57 -06:00 committed by GitHub
commit 9c9db5ba1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 244 additions and 226 deletions

@ -1 +1 @@
Subproject commit b9423d604eca52f3ea3c3f1ded52c0ad07248837 Subproject commit 516fa886ab5f94bbc32d29e50711bdccc9cbd154

View file

@ -56,7 +56,7 @@ class _ConfirmTransactionViewState
final note = transactionInfo["note"] as String? ?? ""; final note = transactionInfo["note"] as String? ?? "";
final manager = final manager =
ref.read(walletsChangeNotifierProvider).getManager(walletId); ref.read(walletsChangeNotifierProvider).getManager(walletId);
try { try {
final txid = await manager.confirmSend(txData: transactionInfo); final txid = await manager.confirmSend(txData: transactionInfo);
@ -79,7 +79,7 @@ class _ConfirmTransactionViewState
showFloatingFlushBar( showFloatingFlushBar(
type: FlushBarType.warning, type: FlushBarType.warning,
message: message:
"Connection failed. Please check the address and try again.", "Connection failed. Please check the address and try again.",
context: context, context: context,
), ),
); );
@ -100,10 +100,10 @@ class _ConfirmTransactionViewState
message: e.toString(), message: e.toString(),
rightButton: TextButton( rightButton: TextButton(
style: Theme.of(context).textButtonTheme.style?.copyWith( style: Theme.of(context).textButtonTheme.style?.copyWith(
backgroundColor: MaterialStateProperty.all<Color>( backgroundColor: MaterialStateProperty.all<Color>(
CFColors.buttonGray, CFColors.buttonGray,
), ),
), ),
child: Text( child: Text(
"Ok", "Ok",
style: STextStyles.button.copyWith( style: STextStyles.button.copyWith(
@ -212,9 +212,9 @@ class _ConfirmTransactionViewState
.select((value) => value.locale), .select((value) => value.locale),
), ),
)} ${ref.watch( )} ${ref.watch(
managerProvider managerProvider
.select((value) => value.coin), .select((value) => value.coin),
).ticker}", ).ticker}",
style: STextStyles.itemSubtitle12, style: STextStyles.itemSubtitle12,
textAlign: TextAlign.right, textAlign: TextAlign.right,
), ),
@ -240,9 +240,9 @@ class _ConfirmTransactionViewState
.select((value) => value.locale), .select((value) => value.locale),
), ),
)} ${ref.watch( )} ${ref.watch(
managerProvider managerProvider
.select((value) => value.coin), .select((value) => value.coin),
).ticker}", ).ticker}",
style: STextStyles.itemSubtitle12, style: STextStyles.itemSubtitle12,
textAlign: TextAlign.right, textAlign: TextAlign.right,
), ),
@ -292,9 +292,9 @@ class _ConfirmTransactionViewState
.select((value) => value.locale), .select((value) => value.locale),
), ),
)} ${ref.watch( )} ${ref.watch(
managerProvider managerProvider
.select((value) => value.coin), .select((value) => value.coin),
).ticker}", ).ticker}",
style: STextStyles.itemSubtitle12, style: STextStyles.itemSubtitle12,
textAlign: TextAlign.right, textAlign: TextAlign.right,
), ),
@ -306,18 +306,18 @@ class _ConfirmTransactionViewState
), ),
TextButton( TextButton(
style: style:
Theme.of(context).textButtonTheme.style?.copyWith( Theme.of(context).textButtonTheme.style?.copyWith(
backgroundColor: backgroundColor:
MaterialStateProperty.all<Color>( MaterialStateProperty.all<Color>(
CFColors.stackAccent, CFColors.stackAccent,
), ),
), ),
onPressed: () async { onPressed: () async {
final unlocked = await Navigator.push( final unlocked = await Navigator.push(
context, context,
RouteGenerator.getRoute( RouteGenerator.getRoute(
shouldUseMaterialRoute: shouldUseMaterialRoute:
RouteGenerator.useMaterialPageRoute, RouteGenerator.useMaterialPageRoute,
builder: (_) => const LockscreenView( builder: (_) => const LockscreenView(
showBackButton: true, showBackButton: true,
popOnSuccess: true, popOnSuccess: true,
@ -325,9 +325,9 @@ class _ConfirmTransactionViewState
routeOnSuccess: "", routeOnSuccess: "",
biometricsCancelButtonString: "CANCEL", biometricsCancelButtonString: "CANCEL",
biometricsLocalizedReason: biometricsLocalizedReason:
"Authenticate to send transaction", "Authenticate to send transaction",
biometricsAuthenticationTitle: biometricsAuthenticationTitle:
"Confirm Transaction", "Confirm Transaction",
), ),
settings: const RouteSettings( settings: const RouteSettings(
name: "/confirmsendlockscreen"), name: "/confirmsendlockscreen"),

View file

@ -7,6 +7,7 @@ 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:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:mutex/mutex.dart'; import 'package:mutex/mutex.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@ -72,123 +73,110 @@ Future<void> executeNative(Map<String, dynamic> arguments) async {
final function = arguments['function'] as String; final function = arguments['function'] as String;
try { try {
if (function == "scanOutPuts") { if (function == "scanOutPuts") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
final startHeight = arguments['startHeight'] as int?; final startHeight = arguments['startHeight'] as int?;
final numberOfBlocks = arguments['numberOfBlocks'] as int?; final numberOfBlocks = arguments['numberOfBlocks'] as int?;
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || if (!(wallet == null ||
password == null ||
startHeight == null || startHeight == null ||
numberOfBlocks == null)) { numberOfBlocks == null)) {
var outputs = var outputs =
await scanOutPuts(config, password, startHeight, numberOfBlocks); await scanOutPuts(wallet, startHeight, numberOfBlocks);
result['outputs'] = outputs; result['outputs'] = outputs;
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "getPendingSlates") { } else if (function == "getPendingSlates") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
final secretKeyIndex = arguments['secretKeyIndex'] as int?; final secretKeyIndex = arguments['secretKeyIndex'] as int?;
final slates = arguments['slates'] as String; final slates = arguments['slates'] as String;
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || password == null || secretKeyIndex == null)) { if (!(wallet == null || secretKeyIndex == null)) {
Logging.instance Logging.instance
.log("SECRET_KEY_INDEX_IS $secretKeyIndex", level: LogLevel.Info); .log("SECRET_KEY_INDEX_IS $secretKeyIndex", level: LogLevel.Info);
result['result'] = result['result'] =
await getPendingSlates(config, password, secretKeyIndex, slates); await getPendingSlates(wallet, secretKeyIndex, slates);
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "subscribeRequest") { } else if (function == "subscribeRequest") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
final secretKeyIndex = arguments['secretKeyIndex'] as int?; final secretKeyIndex = arguments['secretKeyIndex'] as int?;
final epicboxConfig = arguments['epicboxConfig'] as String?; final epicboxConfig = arguments['epicboxConfig'] as String?;
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || if (!(wallet == null ||
password == null ||
secretKeyIndex == null || secretKeyIndex == null ||
epicboxConfig == null)) { epicboxConfig == null)) {
Logging.instance Logging.instance
.log("SECRET_KEY_INDEX_IS $secretKeyIndex", level: LogLevel.Info); .log("SECRET_KEY_INDEX_IS $secretKeyIndex", level: LogLevel.Info);
result['result'] = await getSubscribeRequest( result['result'] = await getSubscribeRequest(
config, password, secretKeyIndex, epicboxConfig); wallet, secretKeyIndex, epicboxConfig);
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "processSlates") { } else if (function == "processSlates") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
final slates = arguments['slates']; final slates = arguments['slates'];
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || password == null || slates == null)) { if (!(wallet == null || slates == null)) {
result['result'] = result['result'] =
await processSlates(config, password, slates.toString()); await processSlates(wallet, slates.toString());
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "getWalletInfo") { } else if (function == "getWalletInfo") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
final refreshFromNode = arguments['refreshFromNode'] as int?; final refreshFromNode = arguments['refreshFromNode'] as int?;
final minimumConfirmations = arguments['minimumConfirmations'] as int?; final minimumConfirmations = arguments['minimumConfirmations'] as int?;
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || if (!(wallet == null ||
password == null ||
refreshFromNode == null || refreshFromNode == null ||
minimumConfirmations == null)) { minimumConfirmations == null)) {
var res = await getWalletInfo( var res = await getWalletInfo(
config, password, refreshFromNode, minimumConfirmations); wallet, refreshFromNode, minimumConfirmations);
result['result'] = res; result['result'] = res;
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "getTransactions") { } else if (function == "getTransactions") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
final refreshFromNode = arguments['refreshFromNode'] as int?; final refreshFromNode = arguments['refreshFromNode'] as int?;
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || password == null || refreshFromNode == null)) { if (!(wallet == null || refreshFromNode == null)) {
var res = await getTransactions(config, password, refreshFromNode); var res = await getTransactions(wallet, refreshFromNode);
result['result'] = res; result['result'] = res;
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "startSync") { } else if (function == "startSync") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
const int refreshFromNode = 1; const int refreshFromNode = 1;
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || password == null)) { if (!(wallet == null)) {
var res = await getWalletInfo(config, password, refreshFromNode, 10); var res = await getWalletInfo(wallet, refreshFromNode, 10);
result['result'] = res; result['result'] = res;
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "getTransactionFees") { } else if (function == "getTransactionFees") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
final amount = arguments['amount'] as int?; final amount = arguments['amount'] as int?;
final minimumConfirmations = arguments['minimumConfirmations'] as int?; final minimumConfirmations = arguments['minimumConfirmations'] as int?;
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || if (!(wallet == null ||
password == null ||
amount == null || amount == null ||
minimumConfirmations == null)) { minimumConfirmations == null)) {
var res = await getTransactionFees( var res = await getTransactionFees(
config, password, amount, minimumConfirmations); wallet, amount, minimumConfirmations);
result['result'] = res; result['result'] = res;
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "createTransaction") { } else if (function == "createTransaction") {
final config = arguments['config'] as String?; final wallet = arguments['wallet'] as String?;
final password = arguments['password'] as String?;
final amount = arguments['amount'] as int?; final amount = arguments['amount'] as int?;
final address = arguments['address'] as String?; final address = arguments['address'] as String?;
final secretKeyIndex = arguments['secretKeyIndex'] as int?; final secretKeyIndex = arguments['secretKeyIndex'] as int?;
@ -196,19 +184,41 @@ Future<void> executeNative(Map<String, dynamic> arguments) async {
final minimumConfirmations = arguments['minimumConfirmations'] as int?; final minimumConfirmations = arguments['minimumConfirmations'] as int?;
Map<String, dynamic> result = {}; Map<String, dynamic> result = {};
if (!(config == null || if (!(wallet == null ||
password == null ||
amount == null || amount == null ||
address == null || address == null ||
secretKeyIndex == null || secretKeyIndex == null ||
epicboxConfig == null || epicboxConfig == null ||
minimumConfirmations == null)) { minimumConfirmations == null)) {
var res = await createTransaction(config, password, amount, address, var res = await createTransaction(wallet, amount, address,
secretKeyIndex, epicboxConfig, minimumConfirmations); secretKeyIndex, epicboxConfig, minimumConfirmations);
result['result'] = res; result['result'] = res;
sendPort.send(result); sendPort.send(result);
return; return;
} }
} else if (function == "txHttpSend") {
final wallet = arguments['wallet'] as String?;
final selectionStrategyIsAll = arguments['selectionStrategyIsAll'] as int?;
final minimumConfirmations = arguments['minimumConfirmations'] as int?;
final message = arguments['message'] as String?;
final amount = arguments['amount'] as int?;
final address = arguments['address'] as String?;
Map<String, dynamic> result = {};
if (!(wallet == null ||
selectionStrategyIsAll == null ||
minimumConfirmations == null ||
message == null ||
amount == null ||
address == null)) {
var res = await txHttpSend(wallet, selectionStrategyIsAll,
minimumConfirmations, message, amount, address);
result['result'] = res;
sendPort.send(result);
return;
}
} }
Logging.instance.log( Logging.instance.log(
"Error Arguments for $function not formatted correctly", "Error Arguments for $function not formatted correctly",
@ -236,14 +246,14 @@ void stop(ReceivePort port) {
// Keep Wrapper functions outside of the class to avoid memory leaks and errors about receive ports and illegal arguments. // Keep Wrapper functions outside of the class to avoid memory leaks and errors about receive ports and illegal arguments.
// TODO: Can get rid of this wrapper and call it in a full isolate instead of compute() if we want more control over this // TODO: Can get rid of this wrapper and call it in a full isolate instead of compute() if we want more control over this
Future<String> _cancelTransactionWrapper( Future<String> _cancelTransactionWrapper(
Tuple3<String, String, String> data) async { Tuple2<String, String> data) async {
// assuming this returns an empty string on success // assuming this returns an empty string on success
// or an error message string on failure // or an error message string on failure
return cancelTransaction(data.item1, data.item2, data.item3); return cancelTransaction(data.item1, data.item2);
} }
Future<String> _deleteWalletWrapper(Tuple2<String, String> data) async { Future<String> _deleteWalletWrapper(String wallet) async {
return deleteWallet(data.item1, data.item2); return deleteWallet(wallet);
} }
Future<String> deleteEpicWallet({ Future<String> deleteEpicWallet({
@ -266,9 +276,9 @@ Future<String> deleteEpicWallet({
config = jsonEncode(editConfig); config = jsonEncode(editConfig);
} }
final password = await secureStore.read(key: '${walletId}_password'); final wallet = await secureStore.read(key: '${walletId}_wallet');
return compute(_deleteWalletWrapper, Tuple2(config!, password!)); return compute(_deleteWalletWrapper, wallet!);
} }
Future<String> _initWalletWrapper( Future<String> _initWalletWrapper(
@ -279,9 +289,9 @@ Future<String> _initWalletWrapper(
} }
Future<String> _initGetAddressInfoWrapper( Future<String> _initGetAddressInfoWrapper(
Tuple4<String, String, int, String> data) async { Tuple3<String, int, String> data) async {
String walletAddress = String walletAddress =
getAddressInfo(data.item1, data.item2, data.item3, data.item4); getAddressInfo(data.item1, data.item2, data.item3);
return walletAddress; return walletAddress;
} }
@ -575,16 +585,14 @@ class EpicCashWallet extends CoinServiceAPI {
Future<String> startSync() async { Future<String> startSync() async {
Logging.instance.log("request start sync", level: LogLevel.Info); Logging.instance.log("request start sync", level: LogLevel.Info);
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
if (!syncMutex.isLocked) { if (!syncMutex.isLocked) {
await syncMutex.protect(() async { await syncMutex.protect(() async {
Logging.instance.log("sync started", level: LogLevel.Info); Logging.instance.log("sync started", level: LogLevel.Info);
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "startSync", "function": "startSync",
"config": config, "wallet": wallet!,
"password": password!,
}, name: walletName); }, name: walletName);
this.receivePort = receivePort; this.receivePort = receivePort;
@ -607,17 +615,14 @@ class EpicCashWallet extends CoinServiceAPI {
} }
Future<String> allWalletBalances() async { Future<String> allWalletBalances() async {
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
const refreshFromNode = 0; const refreshFromNode = 0;
dynamic message; dynamic message;
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "getWalletInfo", "function": "getWalletInfo",
"config": config, "wallet": wallet!,
"password": password!,
"refreshFromNode": refreshFromNode, "refreshFromNode": refreshFromNode,
"minimumConfirmations": MINIMUM_CONFIRMATIONS, "minimumConfirmations": MINIMUM_CONFIRMATIONS,
}, name: walletName); }, name: walletName);
@ -663,9 +668,7 @@ class EpicCashWallet extends CoinServiceAPI {
late PriceAPI _priceAPI; late PriceAPI _priceAPI;
Future<String> cancelPendingTransactionAndPost(String tx_slate_id) async { Future<String> cancelPendingTransactionAndPost(String tx_slate_id) async {
final String config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final String password =
(await _secureStore.read(key: '${_walletId}_password'))!;
final int? receivingIndex = DB.instance final int? receivingIndex = DB.instance
.get<dynamic>(boxName: walletId, key: "receivingIndex") as int?; .get<dynamic>(boxName: walletId, key: "receivingIndex") as int?;
final epicboxConfig = final epicboxConfig =
@ -688,8 +691,7 @@ class EpicCashWallet extends CoinServiceAPI {
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "subscribeRequest", "function": "subscribeRequest",
"config": config, "wallet": wallet,
"password": password,
"secretKeyIndex": currentReceivingIndex!, "secretKeyIndex": currentReceivingIndex!,
"epicboxConfig": epicboxConfig, "epicboxConfig": epicboxConfig,
}, name: walletName); }, name: walletName);
@ -724,17 +726,15 @@ class EpicCashWallet extends CoinServiceAPI {
// //
/// returns an empty String on success, error message on failure /// returns an empty String on success, error message on failure
Future<String> cancelPendingTransaction(String tx_slate_id) async { Future<String> cancelPendingTransaction(String tx_slate_id) async {
final String config = await getRealConfig(); final String wallet =
final String password = (await _secureStore.read(key: '${_walletId}_wallet'))!;
(await _secureStore.read(key: '${_walletId}_password'))!;
String? result; String? result;
await m.protect(() async { await m.protect(() async {
result = await compute( result = await compute(
_cancelTransactionWrapper, _cancelTransactionWrapper,
Tuple3( Tuple2(
config, wallet,
password,
tx_slate_id, tx_slate_id,
), ),
); );
@ -745,45 +745,71 @@ class EpicCashWallet extends CoinServiceAPI {
@override @override
Future<String> confirmSend({required Map<String, dynamic> txData}) async { Future<String> confirmSend({required Map<String, dynamic> txData}) async {
try { try {
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
final epicboxConfig = final epicboxConfig =
await _secureStore.read(key: '${_walletId}_epicboxConfig'); await _secureStore.read(key: '${_walletId}_epicboxConfig');
// TODO determine whether it is worth sending change to a change address. // TODO determine whether it is worth sending change to a change address.
dynamic message; dynamic message;
String receiverAddress = txData['addresss'] as String;
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ if (receiverAddress.startsWith("http://") || receiverAddress.startsWith("https://")) {
"function": "createTransaction", const int selectionStrategyIsAll = 0;
"config": config, ReceivePort receivePort = await getIsolate({
"password": password!, "function": "txHttpSend",
"amount": txData['recipientAmt'], "wallet": wallet!,
"address": txData['addresss'], "selectionStrategyIsAll": selectionStrategyIsAll,
"secretKeyIndex": 0, "minimumConfirmations": MINIMUM_CONFIRMATIONS,
"epicboxConfig": epicboxConfig!, "message": "",
"minimumConfirmations": MINIMUM_CONFIRMATIONS, "amount": txData['recipientAmt'],
}, name: walletName); "address": txData['addresss']
}, name: walletName);
message = await receivePort.first; message = await receivePort.first;
if (message is String) {
// TODO: throw BadEpicHttpAddressException in the case where a send fails due to bad http address Logging.instance
// throw BadEpicHttpAddressException(); .log("this is a string $message", level: LogLevel.Error);
stop(receivePort);
if (message is String) { throw Exception("txHttpSend isolate failed");
Logging.instance }
.log("this is a string $message", level: LogLevel.Error);
stop(receivePort); stop(receivePort);
throw Exception("createTransaction isolate failed"); Logging.instance.log('Closing txHttpSend!\n $message',
level: LogLevel.Info);
} else {
ReceivePort receivePort = await getIsolate({
"function": "createTransaction",
"wallet": wallet!,
"amount": txData['recipientAmt'],
"address": txData['addresss'],
"secretKeyIndex": 0,
"epicboxConfig": epicboxConfig!,
"minimumConfirmations": MINIMUM_CONFIRMATIONS,
}, name: walletName);
message = await receivePort.first;
if (message is String) {
Logging.instance
.log("this is a string $message", level: LogLevel.Error);
stop(receivePort);
throw Exception("createTransaction isolate failed");
}
stop(receivePort);
Logging.instance.log('Closing createTransaction!\n $message',
level: LogLevel.Info);
} }
stop(receivePort);
Logging.instance.log('Closing createTransaction!\n $message',
level: LogLevel.Info);
}); });
// return message; // return message;
final String sendTx = message['result'] as String; final String sendTx = message['result'] as String;
if (sendTx.contains("Error")) {
throw BadEpicHttpAddressException(message: sendTx);
}
await putSendToAddresses(sendTx); await putSendToAddresses(sendTx);
Logging.instance.log("CONFIRM_RESULT_IS $sendTx", level: LogLevel.Info); Logging.instance.log("CONFIRM_RESULT_IS $sendTx", level: LogLevel.Info);
final decodeData = json.decode(sendTx); final decodeData = json.decode(sendTx);
@ -792,22 +818,30 @@ class EpicCashWallet extends CoinServiceAPI {
String errorMessage = decodeData[1] as String; String errorMessage = decodeData[1] as String;
throw Exception("Transaction failed with error code $errorMessage"); throw Exception("Transaction failed with error code $errorMessage");
} else { } else {
final postSlateRequest = decodeData[1];
final postToServer = await postSlate( //If it's HTTP send no need to post to epicbox
txData['addresss'] as String, postSlateRequest as String); if (!(receiverAddress.startsWith("http://") || receiverAddress.startsWith("https://"))) {
Logging.instance final postSlateRequest = decodeData[1];
.log("POST_SLATE_IS $postToServer", level: LogLevel.Info); final postToServer = await postSlate(
//await postSlate txData['addresss'] as String, postSlateRequest as String);
Logging.instance
.log("POST_SLATE_IS $postToServer", level: LogLevel.Info);
}
final txCreateResult = decodeData[0]; final txCreateResult = decodeData[0];
// //TODO: second problem // //TODO: second problem
final transaction = txCreateResult[0]; final transaction = json.decode(txCreateResult as String);
// final wallet = await Hive.openBox<dynamic>(_walletId); Logger.print("TX_IS $transaction");
// final slateToAddresses = (await wallet.get("slate_to_address")) as Map?; final tx = transaction[0];
// slateToAddresses![transaction[0]['tx_slate_id']] = txData['addresss']; final txLogEntry = json.decode(tx as String);
// await wallet.put('slate_to_address', slateToAddresses); final txLogEntryFirst = txLogEntry[0];
// return transaction[0]['tx_slate_id'] as String; Logger.print("TX_LOG_ENTRY_IS $txLogEntryFirst");
return ""; final wallet = await Hive.openBox<dynamic>(_walletId);
final slateToAddresses = (await wallet.get("slate_to_address")) as Map?;
slateToAddresses?[txLogEntryFirst['tx_slate_id']] = txData['addresss'];
await wallet.put('slate_to_address', slateToAddresses);
return txLogEntryFirst['tx_slate_id'] as String;
} }
} catch (e, s) { } catch (e, s) {
Logging.instance.log("Error sending $e - $s", level: LogLevel.Error); Logging.instance.log("Error sending $e - $s", level: LogLevel.Error);
@ -821,8 +855,7 @@ class EpicCashWallet extends CoinServiceAPI {
Future<String> _getCurrentAddressForChain( Future<String> _getCurrentAddressForChain(
int chain, int chain,
) async { ) async {
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
final epicboxConfig = final epicboxConfig =
await _secureStore.read(key: '${_walletId}_epicboxConfig'); await _secureStore.read(key: '${_walletId}_epicboxConfig');
@ -830,7 +863,7 @@ class EpicCashWallet extends CoinServiceAPI {
await m.protect(() async { await m.protect(() async {
walletAddress = await compute( walletAddress = await compute(
_initGetAddressInfoWrapper, _initGetAddressInfoWrapper,
Tuple4(config, password!, chain, epicboxConfig!), Tuple3(wallet!, chain, epicboxConfig!),
); );
}); });
Logging.instance Logging.instance
@ -935,6 +968,13 @@ class EpicCashWallet extends CoinServiceAPI {
Logging.instance.log("Opening existing ${coin.prettyName} wallet", Logging.instance.log("Opening existing ${coin.prettyName} wallet",
level: LogLevel.Info); level: LogLevel.Info);
final config = await getRealConfig();
final password =
await _secureStore.read(key: '${_walletId}_password');
final walletOpen = openWallet(config!, password!);
await _secureStore.write(key: '${_walletId}_wallet', value: walletOpen);
if ((DB.instance.get<dynamic>(boxName: walletId, key: "id")) == null) { if ((DB.instance.get<dynamic>(boxName: walletId, key: "id")) == null) {
debugPrint("Exception was thrown"); debugPrint("Exception was thrown");
throw Exception( throw Exception(
@ -952,8 +992,7 @@ class EpicCashWallet extends CoinServiceAPI {
} }
Future<void> storeEpicboxInfo() async { Future<void> storeEpicboxInfo() async {
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
int index = 0; int index = 0;
Logging.instance.log("This index is $index", level: LogLevel.Info); Logging.instance.log("This index is $index", level: LogLevel.Info);
@ -963,7 +1002,7 @@ class EpicCashWallet extends CoinServiceAPI {
await m.protect(() async { await m.protect(() async {
walletAddress = await compute( walletAddress = await compute(
_initGetAddressInfoWrapper, _initGetAddressInfoWrapper,
Tuple4(config, password!, index, epicboxConfig!), Tuple3(wallet!, index, epicboxConfig!),
); );
}); });
Logging.instance Logging.instance
@ -1023,6 +1062,10 @@ class EpicCashWallet extends CoinServiceAPI {
); );
}); });
//Open wallet
final walletOpen = openWallet(stringConfig, password);
await _secureStore.write(key: '${_walletId}_wallet', value: walletOpen);
//Store Epic box address info //Store Epic box address info
await storeEpicboxInfo(); await storeEpicboxInfo();
@ -1121,16 +1164,14 @@ class EpicCashWallet extends CoinServiceAPI {
Future<int> nativeFee(int satoshiAmount, Future<int> nativeFee(int satoshiAmount,
{bool ifErrorEstimateFee = false}) async { {bool ifErrorEstimateFee = false}) async {
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
try { try {
String? transactionFees; String? transactionFees;
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "getTransactionFees", "function": "getTransactionFees",
"config": config, "wallet": wallet!,
"password": password!,
"amount": satoshiAmount, "amount": satoshiAmount,
"minimumConfirmations": MINIMUM_CONFIRMATIONS, "minimumConfirmations": MINIMUM_CONFIRMATIONS,
}, name: walletName); }, name: walletName);
@ -1256,8 +1297,8 @@ class EpicCashWallet extends CoinServiceAPI {
Future<bool> startScans() async { Future<bool> startScans() async {
try { try {
String stringConfig = await getConfig();
final password = await _secureStore.read(key: '${_walletId}_password'); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
var restoreHeight = var restoreHeight =
DB.instance.get<dynamic>(boxName: walletId, key: "restoreHeight"); DB.instance.get<dynamic>(boxName: walletId, key: "restoreHeight");
@ -1287,8 +1328,7 @@ class EpicCashWallet extends CoinServiceAPI {
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "scanOutPuts", "function": "scanOutPuts",
"config": stringConfig, "wallet": wallet!,
"password": password,
"startHeight": lastScannedBlock, "startHeight": lastScannedBlock,
"numberOfBlocks": MAX_PER_LOOP, "numberOfBlocks": MAX_PER_LOOP,
}, name: walletName); }, name: walletName);
@ -1371,9 +1411,6 @@ class EpicCashWallet extends CoinServiceAPI {
), ),
); );
//Store Epic box address info
await storeEpicboxInfo();
await DB.instance await DB.instance
.put<dynamic>(boxName: walletId, key: "restoreHeight", value: height); .put<dynamic>(boxName: walletId, key: "restoreHeight", value: height);
@ -1402,27 +1439,13 @@ class EpicCashWallet extends CoinServiceAPI {
await DB.instance await DB.instance
.put<dynamic>(boxName: walletId, key: "isFavorite", value: false); .put<dynamic>(boxName: walletId, key: "isFavorite", value: false);
//Scan wallet //Open Wallet
await m.protect(() async { final walletOpen = openWallet(stringConfig, password);
ReceivePort receivePort = await getIsolate({ await _secureStore.write(key: '${_walletId}_wallet', value: walletOpen);
"function": "scanOutPuts",
"config": stringConfig, //Store Epic box address info
"password": password, await storeEpicboxInfo();
"startHeight": 1550000,
"numberOfBlocks": 100,
}, name: walletName);
var message = await receivePort.first;
if (message is String) {
Logging.instance
.log("this is a string $message", level: LogLevel.Error);
stop(receivePort);
throw Exception("scanOutPuts isolate failed");
}
stop(receivePort);
Logging.instance
.log('Closing scanOutPuts!\n $message', level: LogLevel.Info);
});
} catch (e, s) { } catch (e, s) {
Logging.instance Logging.instance
.log("Error recovering wallet $e\n$s", level: LogLevel.Error); .log("Error recovering wallet $e\n$s", level: LogLevel.Error);
@ -1603,16 +1626,14 @@ class EpicCashWallet extends CoinServiceAPI {
currentReceivingIndex++) { currentReceivingIndex++) {
final currentAddress = final currentAddress =
await _getCurrentAddressForChain(currentReceivingIndex); await _getCurrentAddressForChain(currentReceivingIndex);
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
final epicboxConfig = final epicboxConfig =
await _secureStore.read(key: '${_walletId}_epicboxConfig'); await _secureStore.read(key: '${_walletId}_epicboxConfig');
dynamic subscribeRequest; dynamic subscribeRequest;
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "subscribeRequest", "function": "subscribeRequest",
"config": config, "wallet": wallet,
"password": password,
"secretKeyIndex": currentReceivingIndex, "secretKeyIndex": currentReceivingIndex,
"epicboxConfig": epicboxConfig, "epicboxConfig": epicboxConfig,
}, name: walletName); }, name: walletName);
@ -1651,8 +1672,7 @@ class EpicCashWallet extends CoinServiceAPI {
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "getPendingSlates", "function": "getPendingSlates",
"config": config, "wallet": wallet!,
"password": password,
"secretKeyIndex": currentReceivingIndex, "secretKeyIndex": currentReceivingIndex,
"slates": encoded, "slates": encoded,
}, name: walletName); }, name: walletName);
@ -1683,8 +1703,7 @@ class EpicCashWallet extends CoinServiceAPI {
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "processSlates", "function": "processSlates",
"config": config, "wallet": wallet!,
"password": password,
"slates": slateMessage "slates": slateMessage
}, name: walletName); }, name: walletName);
@ -1704,51 +1723,54 @@ class EpicCashWallet extends CoinServiceAPI {
await deleteSlate(currentAddress, await deleteSlate(currentAddress,
subscribeRequest['signature'] as String, slate as String); subscribeRequest['signature'] as String, slate as String);
} }
var decodedResponse = json.decode(response);
Logging.instance.log("PROCESS_SLATE_RESPONSE $response",
level: LogLevel.Info);
final processStatus = json.decode(decodedResponse[0] as String); if (response.contains("Error Wallet store error: DB Not Found Error")) {
String slateStatus = processStatus['status'] as String; //Already processed - to be deleted
// Logging.instance.log("THIS_TEXT $processStatus"); Logging.instance.log("DELETING_PROCESSED_SLATE",
if (slateStatus == "PendingProcessing") { level: LogLevel.Info);
//Encrypt slate final slateDelete = await deleteSlate(currentAddress, subscribeRequest['signature'] as String, slate as String);
// Logging.instance.log("DELETE_SLATE_RESPONSE $slateDelete",
String encryptedSlate = await getEncryptedSlate(
config,
password!,
slateSender,
currentReceivingIndex,
epicboxConfig!,
decodedResponse[1] as String);
final postSlateToServer =
await postSlate(slateSender, encryptedSlate);
await deleteSlate(currentAddress,
subscribeRequest['signature'] as String, slate as String);
Logging.instance.log("POST_SLATE_RESPONSE $postSlateToServer",
level: LogLevel.Info); level: LogLevel.Info);
} else { } else {
//Finalise Slate var decodedResponse = json.decode(response);
final processSlate = json.decode(decodedResponse[1] as String); final processStatus = json.decode(decodedResponse[0] as String);
Logging.instance.log( String slateStatus = processStatus['status'] as String;
"PROCESSED_SLATE_TO_FINALIZE $processSlate", if (slateStatus == "PendingProcessing") {
level: LogLevel.Info); //Encrypt slate
final tx = json.decode(processSlate[0] as String); String encryptedSlate = await getEncryptedSlate(
Logging.instance.log("TX_IS $tx", level: LogLevel.Info); wallet!,
String txSlateId = tx[0]['tx_slate_id'] as String; slateSender,
Logging.instance currentReceivingIndex,
.log("TX_SLATE_ID_IS $txSlateId", level: LogLevel.Info); epicboxConfig!,
// decodedResponse[1] as String);
final postToNode = await postSlateToNode(
config, password!, currentReceivingIndex, txSlateId); final postSlateToServer =
await deleteSlate(currentAddress, await postSlate(slateSender, encryptedSlate);
subscribeRequest['signature'] as String, slate as String);
Logging.instance.log("POST_SLATE_RESPONSE $postToNode", await deleteSlate(currentAddress,
level: LogLevel.Info); subscribeRequest['signature'] as String, slate as String);
//Post Slate to Node Logging.instance.log("POST_SLATE_RESPONSE $postSlateToServer",
Logging.instance.log("Finalise slate", level: LogLevel.Info); level: LogLevel.Info);
} else {
//Finalise Slate
final processSlate = json.decode(decodedResponse[1] as String);
Logging.instance.log(
"PROCESSED_SLATE_TO_FINALIZE $processSlate",
level: LogLevel.Info);
final tx = json.decode(processSlate[0] as String);
Logging.instance.log("TX_IS $tx", level: LogLevel.Info);
String txSlateId = tx[0]['tx_slate_id'] as String;
Logging.instance
.log("TX_SLATE_ID_IS $txSlateId", level: LogLevel.Info);
final postToNode = await postSlateToNode(
wallet!, txSlateId);
await deleteSlate(currentAddress,
subscribeRequest['signature'] as String, slate as String);
Logging.instance.log("POST_SLATE_RESPONSE $postToNode",
level: LogLevel.Info);
//Post Slate to Node
Logging.instance.log("Finalise slate", level: LogLevel.Info);
}
} }
} catch (e, s) { } catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Info); Logging.instance.log("$e\n$s", level: LogLevel.Info);
@ -1766,8 +1788,7 @@ class EpicCashWallet extends CoinServiceAPI {
Future<bool> processAllCancels() async { Future<bool> processAllCancels() async {
Logging.instance.log("processAllCancels", level: LogLevel.Info); Logging.instance.log("processAllCancels", level: LogLevel.Info);
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
final epicboxConfig = final epicboxConfig =
await _secureStore.read(key: '${_walletId}_epicboxConfig'); await _secureStore.read(key: '${_walletId}_epicboxConfig');
final int? receivingIndex = DB.instance final int? receivingIndex = DB.instance
@ -1783,8 +1804,7 @@ class EpicCashWallet extends CoinServiceAPI {
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "subscribeRequest", "function": "subscribeRequest",
"config": config, "wallet": wallet!,
"password": password,
"secretKeyIndex": currentReceivingIndex, "secretKeyIndex": currentReceivingIndex,
"epicboxConfig": epicboxConfig, "epicboxConfig": epicboxConfig,
}, name: walletName); }, name: walletName);
@ -2054,16 +2074,14 @@ class EpicCashWallet extends CoinServiceAPI {
Future<TransactionData> _fetchTransactionData() async { Future<TransactionData> _fetchTransactionData() async {
final currentChainHeight = await chainHeight; final currentChainHeight = await chainHeight;
final config = await getRealConfig(); final wallet = await _secureStore.read(key: '${_walletId}_wallet');
final password = await _secureStore.read(key: '${_walletId}_password');
const refreshFromNode = 0; const refreshFromNode = 0;
dynamic message; dynamic message;
await m.protect(() async { await m.protect(() async {
ReceivePort receivePort = await getIsolate({ ReceivePort receivePort = await getIsolate({
"function": "getTransactions", "function": "getTransactions",
"config": config, "wallet": wallet!,
"password": password!,
"refreshFromNode": refreshFromNode, "refreshFromNode": refreshFromNode,
}, name: walletName); }, name: walletName);