insert inputs/outputs after finishing tx parse

This commit is contained in:
julian 2023-01-13 13:25:09 -06:00
parent 6310f0b1c7
commit 94e6ebf53b
6 changed files with 77 additions and 267 deletions

View file

@ -1998,27 +1998,23 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
} }
} }
bool _duplicateTxCheck( // bool _duplicateTxCheck(
List<Map<String, dynamic>> allTransactions, String txid) { // List<Map<String, dynamic>> allTransactions, String txid) {
for (int i = 0; i < allTransactions.length; i++) { // for (int i = 0; i < allTransactions.length; i++) {
if (allTransactions[i]["txid"] == txid) { // if (allTransactions[i]["txid"] == txid) {
return true; // return true;
} // }
} // }
return false; // return false;
} // }
Future<void> _refreshTransactions() async { Future<void> _refreshTransactions() async {
final List<isar_models.Address> allAddresses = final List<isar_models.Address> allAddresses =
await _fetchAllOwnAddresses(); await _fetchAllOwnAddresses();
final receivingAddresses = allAddresses final Set<Map<String, dynamic>> allReceivingTxHashes =
.where((e) => e.subType == isar_models.AddressSubType.receiving); (await _fetchHistory(allAddresses.map((e) => e.value).toList()))
final changeAddresses = allAddresses .toSet();
.where((e) => e.subType == isar_models.AddressSubType.change);
final List<Map<String, dynamic>> allReceivingTxHashes =
await _fetchHistory(receivingAddresses.map((e) => e.value).toList());
// // prefetch/cache // // prefetch/cache
// Set<String> hashes = {}; // Set<String> hashes = {};
@ -2056,23 +2052,26 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
} }
} }
Set<String> vHashes = {}; // // prefetch/cache
for (final txObject in allTransactions) { // Set<String> vHashes = {};
for (int i = 0; i < (txObject["vin"] as List).length; i++) { // for (final txObject in allTransactions) {
final input = txObject["vin"]![i] as Map; // for (int i = 0; i < (txObject["vin"] as List).length; i++) {
final prevTxid = input["txid"] as String; // final input = txObject["vin"]![i] as Map;
vHashes.add(prevTxid); // final prevTxid = input["txid"] as String;
} // vHashes.add(prevTxid);
} // }
await fastFetch(vHashes.toList()); // }
// await fastFetch(vHashes.toList());
final List<isar_models.Transaction> txns = []; final List<
Tuple3<isar_models.Transaction, List<isar_models.Output>,
List<isar_models.Input>>> txnsData = [];
for (final txObject in allTransactions) { for (final txObject in allTransactions) {
print("========================================================="); print("=========================================================");
log(txObject.toString()); log(txObject.toString());
final txn = await parseTransaction( final data = await parseTransaction(
txObject, txObject,
cachedElectrumXClient, cachedElectrumXClient,
allAddresses, allAddresses,
@ -2080,12 +2079,40 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
MINIMUM_CONFIRMATIONS, MINIMUM_CONFIRMATIONS,
); );
txns.add(txn); txnsData.add(data);
} }
await isar.writeTxn(() async { await isar.writeTxn(() async {
await isar.transactions for (final data in txnsData) {
.deleteAllByTxid(txns.map((e) => e.txid).toList(growable: false)); final tx = data.item1;
await isar.transactions.putAll(txns);
final prevTx =
await isar.transactions.where().txidEqualTo(tx.txid).findFirst();
if (prevTx != null) {
tx.note.value = prevTx.note.value;
await isar.transactions.delete(prevTx.id);
}
// save transaction
await isar.transactions.put(tx);
// link and save outputs
if (data.item2.isNotEmpty) {
await isar.outputs.putAll(data.item2);
tx.outputs.addAll(data.item2);
await tx.outputs.save();
}
// link and save inputs
if (data.item3.isNotEmpty) {
await isar.inputs.putAll(data.item3);
tx.inputs.addAll(data.item3);
await tx.inputs.save();
}
await tx.address.save();
await tx.note.save();
}
}); });
} }
@ -2749,6 +2776,9 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
await isar.writeTxn(() async { await isar.writeTxn(() async {
await isar.transactions.clear(); await isar.transactions.clear();
await isar.inputs.clear();
await isar.outputs.clear();
await isar.utxos.clear();
await isar.addresses.clear(); await isar.addresses.clear();
}); });
@ -2792,106 +2822,6 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Logging.instance.log("starting rescan restore", level: LogLevel.Info); // Logging.instance.log("starting rescan restore", level: LogLevel.Info);
// //
// // restore from backup // // restore from backup
// // p2pkh
// final tempReceivingAddressesP2PKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingAddressesP2PKH_BACKUP');
// final tempChangeAddressesP2PKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'changeAddressesP2PKH_BACKUP');
// final tempReceivingIndexP2PKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingIndexP2PKH_BACKUP');
// final tempChangeIndexP2PKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'changeIndexP2PKH_BACKUP');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingAddressesP2PKH',
// value: tempReceivingAddressesP2PKH);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeAddressesP2PKH',
// value: tempChangeAddressesP2PKH);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingIndexP2PKH',
// value: tempReceivingIndexP2PKH);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeIndexP2PKH',
// value: tempChangeIndexP2PKH);
// await DB.instance.delete<dynamic>(
// key: 'receivingAddressesP2PKH_BACKUP', boxName: walletId);
// await DB.instance
// .delete<dynamic>(key: 'changeAddressesP2PKH_BACKUP', boxName: walletId);
// await DB.instance
// .delete<dynamic>(key: 'receivingIndexP2PKH_BACKUP', boxName: walletId);
// await DB.instance
// .delete<dynamic>(key: 'changeIndexP2PKH_BACKUP', boxName: walletId);
//
// // p2Sh
// final tempReceivingAddressesP2SH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingAddressesP2SH_BACKUP');
// final tempChangeAddressesP2SH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'changeAddressesP2SH_BACKUP');
// final tempReceivingIndexP2SH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingIndexP2SH_BACKUP');
// final tempChangeIndexP2SH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'changeIndexP2SH_BACKUP');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingAddressesP2SH',
// value: tempReceivingAddressesP2SH);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeAddressesP2SH',
// value: tempChangeAddressesP2SH);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingIndexP2SH',
// value: tempReceivingIndexP2SH);
// await DB.instance.put<dynamic>(
// boxName: walletId, key: 'changeIndexP2SH', value: tempChangeIndexP2SH);
// await DB.instance.delete<dynamic>(
// key: 'receivingAddressesP2SH_BACKUP', boxName: walletId);
// await DB.instance
// .delete<dynamic>(key: 'changeAddressesP2SH_BACKUP', boxName: walletId);
// await DB.instance
// .delete<dynamic>(key: 'receivingIndexP2SH_BACKUP', boxName: walletId);
// await DB.instance
// .delete<dynamic>(key: 'changeIndexP2SH_BACKUP', boxName: walletId);
//
// // p2wpkh
// final tempReceivingAddressesP2WPKH = DB.instance.get<dynamic>(
// boxName: walletId, key: 'receivingAddressesP2WPKH_BACKUP');
// final tempChangeAddressesP2WPKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'changeAddressesP2WPKH_BACKUP');
// final tempReceivingIndexP2WPKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingIndexP2WPKH_BACKUP');
// final tempChangeIndexP2WPKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'changeIndexP2WPKH_BACKUP');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingAddressesP2WPKH',
// value: tempReceivingAddressesP2WPKH);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeAddressesP2WPKH',
// value: tempChangeAddressesP2WPKH);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingIndexP2WPKH',
// value: tempReceivingIndexP2WPKH);
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeIndexP2WPKH',
// value: tempChangeIndexP2WPKH);
// await DB.instance.delete<dynamic>(
// key: 'receivingAddressesP2WPKH_BACKUP', boxName: walletId);
// await DB.instance.delete<dynamic>(
// key: 'changeAddressesP2WPKH_BACKUP', boxName: walletId);
// await DB.instance
// .delete<dynamic>(key: 'receivingIndexP2WPKH_BACKUP', boxName: walletId);
// await DB.instance
// .delete<dynamic>(key: 'changeIndexP2WPKH_BACKUP', boxName: walletId);
//
// // P2PKH derivations // // P2PKH derivations
// final p2pkhReceiveDerivationsString = await _secureStore.read( // final p2pkhReceiveDerivationsString = await _secureStore.read(
// key: "${walletId}_receiveDerivationsP2PKH_BACKUP"); // key: "${walletId}_receiveDerivationsP2PKH_BACKUP");
@ -2943,14 +2873,6 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// await _secureStore.delete( // await _secureStore.delete(
// key: "${walletId}_changeDerivationsP2WPKH_BACKUP"); // key: "${walletId}_changeDerivationsP2WPKH_BACKUP");
// //
// // UTXOs
// final utxoData = DB.instance
// .get<dynamic>(boxName: walletId, key: 'latest_utxo_model_BACKUP');
// await DB.instance.put<dynamic>(
// boxName: walletId, key: 'latest_utxo_model', value: utxoData);
// await DB.instance
// .delete<dynamic>(key: 'latest_utxo_model_BACKUP', boxName: walletId);
//
// Logging.instance.log("rescan restore complete", level: LogLevel.Info); // Logging.instance.log("rescan restore complete", level: LogLevel.Info);
// } // }
// //
@ -2958,117 +2880,6 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Logging.instance.log("starting rescan backup", level: LogLevel.Info); // Logging.instance.log("starting rescan backup", level: LogLevel.Info);
// //
// // backup current and clear data // // backup current and clear data
// // p2pkh
// final tempReceivingAddressesP2PKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingAddressesP2PKH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingAddressesP2PKH_BACKUP',
// value: tempReceivingAddressesP2PKH);
// await DB.instance
// .delete<dynamic>(key: 'receivingAddressesP2PKH', boxName: walletId);
//
// final tempChangeAddressesP2PKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'changeAddressesP2PKH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeAddressesP2PKH_BACKUP',
// value: tempChangeAddressesP2PKH);
// await DB.instance
// .delete<dynamic>(key: 'changeAddressesP2PKH', boxName: walletId);
//
// final tempReceivingIndexP2PKH =
// DB.instance.get<dynamic>(boxName: walletId, key: 'receivingIndexP2PKH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingIndexP2PKH_BACKUP',
// value: tempReceivingIndexP2PKH);
// await DB.instance
// .delete<dynamic>(key: 'receivingIndexP2PKH', boxName: walletId);
//
// final tempChangeIndexP2PKH =
// DB.instance.get<dynamic>(boxName: walletId, key: 'changeIndexP2PKH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeIndexP2PKH_BACKUP',
// value: tempChangeIndexP2PKH);
// await DB.instance
// .delete<dynamic>(key: 'changeIndexP2PKH', boxName: walletId);
//
// // p2sh
// final tempReceivingAddressesP2SH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingAddressesP2SH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingAddressesP2SH_BACKUP',
// value: tempReceivingAddressesP2SH);
// await DB.instance
// .delete<dynamic>(key: 'receivingAddressesP2SH', boxName: walletId);
//
// final tempChangeAddressesP2SH =
// DB.instance.get<dynamic>(boxName: walletId, key: 'changeAddressesP2SH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeAddressesP2SH_BACKUP',
// value: tempChangeAddressesP2SH);
// await DB.instance
// .delete<dynamic>(key: 'changeAddressesP2SH', boxName: walletId);
//
// final tempReceivingIndexP2SH =
// DB.instance.get<dynamic>(boxName: walletId, key: 'receivingIndexP2SH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingIndexP2SH_BACKUP',
// value: tempReceivingIndexP2SH);
// await DB.instance
// .delete<dynamic>(key: 'receivingIndexP2SH', boxName: walletId);
//
// final tempChangeIndexP2SH =
// DB.instance.get<dynamic>(boxName: walletId, key: 'changeIndexP2SH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeIndexP2SH_BACKUP',
// value: tempChangeIndexP2SH);
// await DB.instance
// .delete<dynamic>(key: 'changeIndexP2SH', boxName: walletId);
//
// // p2wpkh
// final tempReceivingAddressesP2WPKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingAddressesP2WPKH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingAddressesP2WPKH_BACKUP',
// value: tempReceivingAddressesP2WPKH);
// await DB.instance
// .delete<dynamic>(key: 'receivingAddressesP2WPKH', boxName: walletId);
//
// final tempChangeAddressesP2WPKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'changeAddressesP2WPKH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeAddressesP2WPKH_BACKUP',
// value: tempChangeAddressesP2WPKH);
// await DB.instance
// .delete<dynamic>(key: 'changeAddressesP2WPKH', boxName: walletId);
//
// final tempReceivingIndexP2WPKH = DB.instance
// .get<dynamic>(boxName: walletId, key: 'receivingIndexP2WPKH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'receivingIndexP2WPKH_BACKUP',
// value: tempReceivingIndexP2WPKH);
// await DB.instance
// .delete<dynamic>(key: 'receivingIndexP2WPKH', boxName: walletId);
//
// final tempChangeIndexP2WPKH =
// DB.instance.get<dynamic>(boxName: walletId, key: 'changeIndexP2WPKH');
// await DB.instance.put<dynamic>(
// boxName: walletId,
// key: 'changeIndexP2WPKH_BACKUP',
// value: tempChangeIndexP2WPKH);
// await DB.instance
// .delete<dynamic>(key: 'changeIndexP2WPKH', boxName: walletId);
//
// // P2PKH derivations // // P2PKH derivations
// final p2pkhReceiveDerivationsString = // final p2pkhReceiveDerivationsString =
// await _secureStore.read(key: "${walletId}_receiveDerivationsP2PKH"); // await _secureStore.read(key: "${walletId}_receiveDerivationsP2PKH");
@ -3117,13 +2928,7 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// await _secureStore.delete(key: "${walletId}_receiveDerivationsP2WPKH"); // await _secureStore.delete(key: "${walletId}_receiveDerivationsP2WPKH");
// await _secureStore.delete(key: "${walletId}_changeDerivationsP2WPKH"); // await _secureStore.delete(key: "${walletId}_changeDerivationsP2WPKH");
// //
// // UTXOs //
// final utxoData =
// DB.instance.get<dynamic>(boxName: walletId, key: 'latest_utxo_model');
// await DB.instance.put<dynamic>(
// boxName: walletId, key: 'latest_utxo_model_BACKUP', value: utxoData);
// await DB.instance
// .delete<dynamic>(key: 'latest_utxo_model', boxName: walletId);
// //
// Logging.instance.log("rescan backup complete", level: LogLevel.Info); // Logging.instance.log("rescan backup complete", level: LogLevel.Info);
// } // }

View file

@ -562,13 +562,15 @@ extension PayNym on DogecoinWallet {
} }
} }
Future<Transaction> parseTransaction( Future<Tuple3<Transaction, List<Output>, List<Input>>> parseTransaction(
Map<String, dynamic> txData, Map<String, dynamic> txData,
dynamic electrumxClient, dynamic electrumxClient,
List<Address> myAddresses, List<Address> myAddresses,
Coin coin, Coin coin,
int minConfirms, int minConfirms,
) async { ) async {
final transactionAddress = txData["address"] as Address;
Set<String> receivingAddresses = myAddresses Set<String> receivingAddresses = myAddresses
.where((e) => e.subType == AddressSubType.receiving) .where((e) => e.subType == AddressSubType.receiving)
.map((e) => e.value) .map((e) => e.value)
@ -672,7 +674,7 @@ Future<Transaction> parseTransaction(
// this should be the address we used to originally fetch the tx so we should // this should be the address we used to originally fetch the tx so we should
// be able to easily figure out if the tx is a send or receive // be able to easily figure out if the tx is a send or receive
tx.address.value = txData["address"] as Address; tx.address.value = transactionAddress;
if (mySentFromAddresses.isNotEmpty && myReceivedOnAddresses.isNotEmpty) { if (mySentFromAddresses.isNotEmpty && myReceivedOnAddresses.isNotEmpty) {
// tx is sent to self // tx is sent to self
@ -694,11 +696,14 @@ Future<Transaction> parseTransaction(
tx.fee = fee; tx.fee = fee;
log("tx.address: ${tx.address}"); log("transactionAddress: $transactionAddress");
log("mySentFromAddresses: $mySentFromAddresses"); log("mySentFromAddresses: $mySentFromAddresses");
log("myReceivedOnAddresses: $myReceivedOnAddresses"); log("myReceivedOnAddresses: $myReceivedOnAddresses");
log("myChangeReceivedOnAddresses: $myChangeReceivedOnAddresses"); log("myChangeReceivedOnAddresses: $myChangeReceivedOnAddresses");
List<Output> outs = [];
List<Input> ins = [];
for (final json in txData["vin"] as List) { for (final json in txData["vin"] as List) {
bool isCoinBase = json['coinbase'] != null; bool isCoinBase = json['coinbase'] != null;
final input = Input(); final input = Input();
@ -709,7 +714,7 @@ Future<Transaction> parseTransaction(
input.isCoinbase = isCoinBase ? isCoinBase : json['is_coinbase'] as bool?; input.isCoinbase = isCoinBase ? isCoinBase : json['is_coinbase'] as bool?;
input.sequence = json['sequence'] as int?; input.sequence = json['sequence'] as int?;
input.innerRedeemScriptAsm = json['innerRedeemscriptAsm'] as String?; input.innerRedeemScriptAsm = json['innerRedeemscriptAsm'] as String?;
tx.inputs.add(input); ins.add(input);
} }
for (final json in txData["vout"] as List) { for (final json in txData["vout"] as List) {
@ -724,7 +729,7 @@ Future<Transaction> parseTransaction(
Decimal.parse(json["value"].toString()), Decimal.parse(json["value"].toString()),
coin, coin,
); );
tx.outputs.add(output); outs.add(output);
} }
tx.height = txData["height"] as int?; tx.height = txData["height"] as int?;
@ -735,5 +740,5 @@ Future<Transaction> parseTransaction(
tx.otherData = null; tx.otherData = null;
tx.isLelantus = null; tx.isLelantus = null;
return tx; return Tuple3(tx, outs, ins);
} }

View file

@ -1887,7 +1887,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// // we don't need to check this but it saves a write tx instead of overwriting the transaction in Isar // // we don't need to check this but it saves a write tx instead of overwriting the transaction in Isar
// if (tx == null) { // if (tx == null) {
await isar.writeTxn(() async { await isar.writeTxn(() async {
await isar.transactions.put(txn); await isar.transactions.put(txn.item1);
}); });
// } // }
} }

View file

@ -3477,7 +3477,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
// // we don't need to check this but it saves a write tx instead of overwriting the transaction in Isar // // we don't need to check this but it saves a write tx instead of overwriting the transaction in Isar
// if (tx == null) { // if (tx == null) {
await isar.writeTxn(() async { await isar.writeTxn(() async {
await isar.transactions.put(txn); await isar.transactions.put(txn.item1);
}); });
// } // }
} }

View file

@ -2197,7 +2197,7 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// // we don't need to check this but it saves a write tx instead of overwriting the transaction in Isar // // we don't need to check this but it saves a write tx instead of overwriting the transaction in Isar
// if (tx == null) { // if (tx == null) {
await isar.writeTxn(() async { await isar.writeTxn(() async {
await isar.transactions.put(txn); await isar.transactions.put(txn.item1);
}); });
// } // }

View file

@ -2174,7 +2174,7 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// // we don't need to check this but it saves a write tx instead of overwriting the transaction in Isar // // we don't need to check this but it saves a write tx instead of overwriting the transaction in Isar
// if (tx == null) { // if (tx == null) {
await isar.writeTxn(() async { await isar.writeTxn(() async {
await isar.transactions.put(txn); await isar.transactions.put(txn.item1);
}); });
// } // }