mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 17:57:40 +00:00
Add EpicTransaction DTO for parsing transactions, clean out mutex stuff for calls to the abstract class
This commit is contained in:
parent
e28c7f5019
commit
3b4de2b2d5
3 changed files with 90 additions and 122 deletions
|
@ -1,22 +1,18 @@
|
|||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
/*
|
||||
* This file is part of Stack Wallet.
|
||||
*
|
||||
* Copyright (c) 2023 Cypher Stack
|
||||
* All Rights Reserved.
|
||||
* The code is distributed under GPLv3 license, see LICENSE file for details.
|
||||
* Generated by Cypher Stack on 2023-10-03
|
||||
*
|
||||
*/
|
||||
|
||||
class EpicTransaction {
|
||||
|
||||
@Index()
|
||||
late final String walletId;
|
||||
|
||||
@Index()
|
||||
final String parentKeyId;
|
||||
|
||||
@Index(unique: true, composite: [CompositeIndex("walletId")])
|
||||
late final int id;
|
||||
|
||||
final int id;
|
||||
final String? txSlateId;
|
||||
|
||||
@enumerated
|
||||
final TransactionType txType;
|
||||
|
||||
final EpicTransactionType txType;
|
||||
final String creationTs;
|
||||
final String confirmationTs;
|
||||
final bool confirmed;
|
||||
|
@ -32,9 +28,6 @@ class EpicTransaction {
|
|||
final int? kernelLookupMinHeight;
|
||||
final String? paymentProof;
|
||||
|
||||
@Backlink(to: "transactions")
|
||||
final address = IsarLink<Address>();
|
||||
|
||||
EpicTransaction({
|
||||
required this.parentKeyId,
|
||||
required this.id,
|
||||
|
@ -56,26 +49,27 @@ class EpicTransaction {
|
|||
this.paymentProof,
|
||||
});
|
||||
|
||||
factory EpicTransaction.fromJson(Map<String, dynamic> json) {
|
||||
factory EpicTransaction.fromJson(dynamic json) {
|
||||
// print("THIS JSON IS $json")
|
||||
return EpicTransaction(
|
||||
parentKeyId: json['parent_key_id'] as String,
|
||||
id: json['id'] as int,
|
||||
txSlateId: json['tx_slate_id'] as String,
|
||||
txType: json['tx_type'] as TransactionType,
|
||||
creationTs: json['creation_ts'] as String,
|
||||
confirmationTs: json['confirmation_ts'] as String,
|
||||
confirmed: json['confirmed'] as bool,
|
||||
numInputs: json['num_inputs'] as int,
|
||||
numOutputs: json['num_outputs'] as int,
|
||||
amountCredited: json['amount_credited'] as String,
|
||||
amountDebited: json['amount_debited'] as String,
|
||||
fee: json['fee'] as String,
|
||||
ttlCutoffHeight: json['ttl_cutoff_height'] as String,
|
||||
id: int.parse(json!['id'].toString()),
|
||||
txSlateId: json['tx_slate_id'].toString(),
|
||||
txType: EpicTransactionType.values.byName(json['tx_type'] as String),
|
||||
creationTs: json['creation_ts'].toString(),
|
||||
confirmationTs: json['confirmation_ts'].toString(),
|
||||
confirmed: bool.parse(json['confirmed'].toString()),
|
||||
numInputs: int.parse(json['num_inputs'].toString()),
|
||||
numOutputs: int.parse(json['num_outputs'].toString()),
|
||||
amountCredited: json['amount_credited'].toString(),
|
||||
amountDebited: json['amount_debited'].toString(),
|
||||
fee: json['fee'].toString(),
|
||||
ttlCutoffHeight: json['ttl_cutoff_height'].toString(),
|
||||
messages: json['messages'] != null ? Messages.fromJson(json['messages'] as Map<String, dynamic>) : null,
|
||||
storedTx: json['stored_tx'] as String,
|
||||
kernelExcess: json['kernel_excess'] as String,
|
||||
kernelLookupMinHeight: json['kernel_lookup_min_height'] as int,
|
||||
paymentProof: json['payment_proof'] as String,
|
||||
storedTx: json['stored_tx'].toString(),
|
||||
kernelExcess: json['kernel_excess'].toString(),
|
||||
kernelLookupMinHeight: json['kernel_lookup_min_height'] == null? null : int.parse(json['kernel_lookup_min_height'].toString()),
|
||||
paymentProof: json['payment_proof'].toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -107,10 +101,10 @@ class Message {
|
|||
|
||||
factory Message.fromJson(Map<String, dynamic> json) {
|
||||
return Message(
|
||||
id: json['id'] as String,
|
||||
publicKey: json['public_key'] as String,
|
||||
message: json['message'] as String,
|
||||
messageSig: json['message_sig'] as String,
|
||||
id: json['id'].toString(),
|
||||
publicKey: json['public_key'].toString(),
|
||||
message: json['message'].toString(),
|
||||
messageSig: json['message_sig'].toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -118,8 +112,8 @@ class Message {
|
|||
|
||||
enum EpicTransactionType {
|
||||
//Use Epic transaction type here
|
||||
outgoing,
|
||||
incoming,
|
||||
sentToSelf, // should we keep this?
|
||||
unknown;
|
||||
TxReceived,
|
||||
TxReceivedCancelled,
|
||||
TxSent,
|
||||
TxSentCancelled, // should we keep this?
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import 'package:stack_wallet_backup/generate_password.dart';
|
|||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/models/balance.dart';
|
||||
import 'package:stackwallet/models/epicbox_config_model.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/epic_transaction.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
|
||||
import 'package:stackwallet/models/node_model.dart';
|
||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||
|
@ -108,16 +109,6 @@ Future<void> executeNative(Map<String, dynamic> arguments) async {
|
|||
sendPort.send(result);
|
||||
return;
|
||||
}
|
||||
} else if (function == "getTransactions") {
|
||||
final wallet = arguments['wallet'] as String?;
|
||||
final refreshFromNode = arguments['refreshFromNode'] as int?;
|
||||
Map<String, dynamic> result = {};
|
||||
if (!(wallet == null || refreshFromNode == null)) {
|
||||
var res = await getTransactions(wallet, refreshFromNode);
|
||||
result['result'] = res;
|
||||
sendPort.send(result);
|
||||
return;
|
||||
}
|
||||
} else if (function == "startSync") {
|
||||
final wallet = arguments['wallet'] as String?;
|
||||
const int refreshFromNode = 1;
|
||||
|
@ -315,12 +306,10 @@ class EpicCashWallet extends CoinServiceAPI
|
|||
key: '${_walletId}_wallet',
|
||||
))!;
|
||||
|
||||
final result = await m.protect(() async {
|
||||
return await epiccash.LibEpiccash.cancelTransaction(
|
||||
wallet: wallet,
|
||||
transactionId: txSlateId,
|
||||
);
|
||||
});
|
||||
final result = await epiccash.LibEpiccash.cancelTransaction(
|
||||
wallet: wallet,
|
||||
transactionId: txSlateId,
|
||||
);
|
||||
Logging.instance.log(
|
||||
"cancel $txSlateId result: $result",
|
||||
level: LogLevel.Info,
|
||||
|
@ -1062,14 +1051,11 @@ class EpicCashWallet extends CoinServiceAPI
|
|||
Future<int> get chainHeight async {
|
||||
try {
|
||||
final config = await getRealConfig();
|
||||
int? latestHeight;
|
||||
await m.protect(() async {
|
||||
latestHeight =
|
||||
await epiccash.LibEpiccash.getChainHeight(config: config);
|
||||
});
|
||||
int? latestHeight =
|
||||
await epiccash.LibEpiccash.getChainHeight(config: config);
|
||||
|
||||
await updateCachedChainHeight(latestHeight!);
|
||||
if (latestHeight! > storedChainHeight) {
|
||||
await updateCachedChainHeight(latestHeight);
|
||||
if (latestHeight > storedChainHeight) {
|
||||
GlobalEventBus.instance.fire(
|
||||
UpdatedInBackgroundEvent(
|
||||
"Updated current chain height in $walletId $walletName!",
|
||||
|
@ -1077,7 +1063,7 @@ class EpicCashWallet extends CoinServiceAPI
|
|||
),
|
||||
);
|
||||
}
|
||||
return latestHeight!;
|
||||
return latestHeight;
|
||||
} catch (e, s) {
|
||||
Logging.instance.log("Exception caught in chainHeight: $e\n$s",
|
||||
level: LogLevel.Error);
|
||||
|
@ -1383,80 +1369,56 @@ class EpicCashWallet extends CoinServiceAPI
|
|||
bool get isConnected => _isConnected;
|
||||
|
||||
Future<void> _refreshTransactions() async {
|
||||
// final currentChainHeight = await chainHeight;
|
||||
|
||||
final wallet = await _secureStore.read(key: '${_walletId}_wallet');
|
||||
const refreshFromNode = 1;
|
||||
|
||||
dynamic message;
|
||||
await m.protect(() async {
|
||||
ReceivePort receivePort = await getIsolate({
|
||||
"function": "getTransactions",
|
||||
"wallet": wallet!,
|
||||
"refreshFromNode": refreshFromNode,
|
||||
}, 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("getTransactions isolate failed");
|
||||
}
|
||||
stop(receivePort);
|
||||
Logging.instance
|
||||
.log('Closing getTransactions!\n $message', level: LogLevel.Info);
|
||||
});
|
||||
// return message;
|
||||
final String transactions = message['result'] as String;
|
||||
|
||||
print("RETURNED TRANSACTIONS IS $transactions");
|
||||
final jsonTransactions = json.decode(transactions) as List;
|
||||
var transactions = await epiccash.LibEpiccash.getTransactions(wallet: wallet!, refreshFromNode: refreshFromNode);
|
||||
|
||||
final List<Tuple2<isar_models.Transaction, isar_models.Address?>> txnsData =
|
||||
[];
|
||||
|
||||
final slatesToCommits = await getSlatesToCommits();
|
||||
|
||||
for (var tx in jsonTransactions) {
|
||||
for (var tx in transactions) {
|
||||
Logging.instance.log("tx: $tx", level: LogLevel.Info);
|
||||
// // TODO: does "confirmed" mean finalized? If so please remove this todo
|
||||
final isConfirmed = tx["confirmed"] as bool;
|
||||
final isConfirmed = tx.confirmed;
|
||||
|
||||
int amt = 0;
|
||||
if (tx["tx_type"] == "TxReceived" ||
|
||||
tx["tx_type"] == "TxReceivedCancelled") {
|
||||
amt = int.parse(tx['amount_credited'] as String);
|
||||
if (tx.txType == EpicTransactionType.TxReceived ||
|
||||
tx.txType == EpicTransactionType.TxReceivedCancelled) {
|
||||
amt = int.parse(tx.amountCredited);
|
||||
} else {
|
||||
int debit = int.parse(tx['amount_debited'] as String);
|
||||
int credit = int.parse(tx['amount_credited'] as String);
|
||||
int fee = int.parse((tx['fee'] ?? "0") as String);
|
||||
int debit = int.parse(tx.amountDebited);
|
||||
int credit = int.parse(tx.amountCredited);
|
||||
int fee = int.parse((tx.fee ?? "0"));
|
||||
amt = debit - credit - fee;
|
||||
}
|
||||
|
||||
DateTime dt = DateTime.parse(tx["creation_ts"] as String);
|
||||
DateTime dt = DateTime.parse(tx.creationTs);
|
||||
|
||||
String? slateId = tx['tx_slate_id'] as String?;
|
||||
String? slateId = tx.txSlateId;
|
||||
String address = slatesToCommits[slateId]
|
||||
?[tx["tx_type"] == "TxReceived" ? "from" : "to"] as String? ??
|
||||
?[tx.txType == EpicTransactionType.TxReceived ? "from" : "to"] as String? ??
|
||||
"";
|
||||
String? commitId = slatesToCommits[slateId]?['commitId'] as String?;
|
||||
tx['numberOfMessages'] = tx['messages']?['messages']?.length;
|
||||
tx['onChainNote'] = tx['messages']?['messages']?[0]?['message'];
|
||||
int? numberOfMessages = tx.messages?.messages.length;
|
||||
String? onChainNote = tx.messages?.messages[0].message;
|
||||
|
||||
int? height;
|
||||
|
||||
if (isConfirmed) {
|
||||
height = tx["kernel_lookup_min_height"] as int? ?? 1;
|
||||
height = tx.kernelLookupMinHeight ?? 1;
|
||||
} else {
|
||||
height = null;
|
||||
}
|
||||
|
||||
final isIncoming = (tx["tx_type"] == "TxReceived" ||
|
||||
tx["tx_type"] == "TxReceivedCancelled");
|
||||
|
||||
final isIncoming = (tx.txType == EpicTransactionType.TxReceived ||
|
||||
tx.txType == EpicTransactionType.TxReceivedCancelled);
|
||||
final txn = isar_models.Transaction(
|
||||
walletId: walletId,
|
||||
txid: commitId ?? tx["id"].toString(),
|
||||
txid: commitId ?? tx.id.toString(),
|
||||
timestamp: (dt.millisecondsSinceEpoch ~/ 1000),
|
||||
type: isIncoming
|
||||
? isar_models.TransactionType.incoming
|
||||
|
@ -1467,19 +1429,17 @@ class EpicCashWallet extends CoinServiceAPI
|
|||
rawValue: BigInt.from(amt),
|
||||
fractionDigits: coin.decimals,
|
||||
).toJsonString(),
|
||||
fee: (tx["fee"] == null) ? 0 : int.parse(tx["fee"] as String),
|
||||
fee: (tx.fee == "null") ? 0 : int.parse(tx.fee!),
|
||||
height: height,
|
||||
isCancelled: tx["tx_type"] == "TxSentCancelled" ||
|
||||
tx["tx_type"] == "TxReceivedCancelled",
|
||||
isCancelled: tx.txType == EpicTransactionType.TxSentCancelled ||
|
||||
tx.txType == EpicTransactionType.TxReceivedCancelled,
|
||||
isLelantus: false,
|
||||
slateId: slateId,
|
||||
nonce: null,
|
||||
otherData: tx['onChainNote'].toString(),
|
||||
otherData: onChainNote,
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
numberOfMessages: ((tx["numberOfMessages"] == null)
|
||||
? 0
|
||||
: tx["numberOfMessages"]) as int,
|
||||
numberOfMessages: numberOfMessages,
|
||||
);
|
||||
|
||||
// txn.address =
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:decimal/decimal.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_libepiccash/epic_cash.dart' as lib_epiccash;
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/epic_transaction.dart';
|
||||
|
||||
///
|
||||
/// Wrapped up calls to flutter_libepiccash.
|
||||
|
@ -263,17 +264,30 @@ abstract class LibEpiccash {
|
|||
///
|
||||
///
|
||||
///
|
||||
static Future<String> getTransaction({
|
||||
static Future<List<EpicTransaction>> getTransactions({
|
||||
required String wallet,
|
||||
required int refreshFromNode,
|
||||
}) async {
|
||||
try {
|
||||
return await compute(_getTransactionsWrapper, (
|
||||
wallet: wallet,
|
||||
refreshFromNode: refreshFromNode,
|
||||
var result = await compute(_getTransactionsWrapper, (
|
||||
wallet: wallet,
|
||||
refreshFromNode: refreshFromNode,
|
||||
));
|
||||
|
||||
if (result.toUpperCase().contains("ERROR")) {
|
||||
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 transaction : ${e.toString()}");
|
||||
throw ("Error getting epic transactions : ${e.toString()}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue