scan following/followers for paynym history

This commit is contained in:
julian 2023-01-31 17:26:10 -06:00
parent a25c03cb5c
commit 19bf4c0df6
2 changed files with 106 additions and 16 deletions

View file

@ -40,6 +40,7 @@ import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/paynym_is_api.dart';
import 'package:stackwallet/utilities/prefs.dart'; import 'package:stackwallet/utilities/prefs.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
@ -704,16 +705,28 @@ class BitcoinWallet extends CoinServiceAPI
...p2shChangeAddressArray, ...p2shChangeAddressArray,
]); ]);
// generate to ensure notification address is in db before refreshing transactions // get own payment code
await getMyNotificationAddress(DerivePathType.bip44); final myCode = await getPaymentCode(DerivePathType.bip44);
// refresh transactions to pick up any received notification transactions // refresh transactions to pick up any received notification transactions
await _refreshTransactions(); await _refreshTransactions();
final Set<String> codesToCheck = {};
final nym = await PaynymIsApi().nym(myCode.toString());
if (nym.value != null) {
for (final follower in nym.value!.followers) {
codesToCheck.add(follower.code);
}
for (final following in nym.value!.following) {
codesToCheck.add(following.code);
}
}
// restore paynym transactions // restore paynym transactions
await restoreAllHistory( await restoreAllHistory(
maxUnusedAddressGap: maxUnusedAddressGap, maxUnusedAddressGap: maxUnusedAddressGap,
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck, maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
paymentCodeStrings: codesToCheck,
); );
await _updateUTXOs(); await _updateUTXOs();
@ -940,6 +953,17 @@ class BitcoinWallet extends CoinServiceAPI
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId)); GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId));
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.1, walletId)); GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.1, walletId));
final myCode = await getPaymentCode(DerivePathType.bip44);
final Set<String> codesToCheck = {};
final nym = await PaynymIsApi().nym(myCode.toString());
if (nym.value != null) {
for (final follower in nym.value!.followers) {
codesToCheck.add(follower.code);
}
for (final following in nym.value!.following) {
codesToCheck.add(following.code);
}
}
final currentHeight = await chainHeight; final currentHeight = await chainHeight;
const storedHeight = 1; //await storedChainHeight; const storedHeight = 1; //await storedChainHeight;
@ -976,6 +1000,7 @@ class BitcoinWallet extends CoinServiceAPI
.fire(RefreshPercentChangedEvent(0.80, walletId)); .fire(RefreshPercentChangedEvent(0.80, walletId));
await fetchFuture; await fetchFuture;
await checkForNotificationTransactionsTo(codesToCheck);
await getAllTxsToWatch(); await getAllTxsToWatch();
GlobalEventBus.instance GlobalEventBus.instance
.fire(RefreshPercentChangedEvent(0.90, walletId)); .fire(RefreshPercentChangedEvent(0.90, walletId));
@ -2828,7 +2853,6 @@ class BitcoinWallet extends CoinServiceAPI
// Add transaction output // Add transaction output
for (var i = 0; i < recipients.length; i++) { for (var i = 0; i < recipients.length; i++) {
print("OURPUT VALUW: ${satoshiAmounts[i]}");
txb.addOutput(recipients[i], satoshiAmounts[i]); txb.addOutput(recipients[i], satoshiAmounts[i]);
} }

View file

@ -749,33 +749,99 @@ mixin PaynymWalletInterface {
.subTypeEqualTo(TransactionSubType.bip47Notification) .subTypeEqualTo(TransactionSubType.bip47Notification)
.findAll(); .findAll();
List<PaymentCode> unBlindedList = []; List<PaymentCode> codes = [];
for (final tx in txns) { for (final tx in txns) {
// tx is sent so we can check the address's otherData for the code String
if (tx.type == TransactionType.outgoing &&
tx.address.value?.otherData != null) {
final codeString =
await paymentCodeStringByKey(tx.address.value!.otherData!);
if (codeString != null &&
codes.where((e) => e.toString() == codeString).isEmpty) {
codes.add(PaymentCode.fromPaymentCode(codeString, _network));
}
} else {
// otherwise we need to un blind the code
final unBlinded = await unBlindedPaymentCodeFromTransaction( final unBlinded = await unBlindedPaymentCodeFromTransaction(
transaction: tx, transaction: tx,
myNotificationAddress: myAddress, myNotificationAddress: myAddress,
); );
if (unBlinded != null && if (unBlinded != null &&
unBlindedList codes.where((e) => e.toString() == unBlinded.toString()).isEmpty) {
.where((e) => e.toString() == unBlinded.toString()) codes.add(unBlinded);
.isEmpty) { }
unBlindedList.add(unBlinded);
} }
} }
return unBlindedList; return codes;
}
Future<void> checkForNotificationTransactionsTo(
Set<String> otherCodeStrings) async {
final sentNotificationTransactions = await _db
.getTransactions(_walletId)
.filter()
.subTypeEqualTo(TransactionSubType.bip47Notification)
.and()
.typeEqualTo(TransactionType.outgoing)
.findAll();
final List<PaymentCode> codes = [];
for (final codeString in otherCodeStrings) {
codes.add(PaymentCode.fromPaymentCode(codeString, _network));
}
for (final tx in sentNotificationTransactions) {
if (tx.address.value != null && tx.address.value!.otherData == null) {
final oldAddress =
await _db.getAddress(_walletId, tx.address.value!.value);
for (final code in codes) {
final notificationAddress = code.notificationAddressP2PKH();
if (notificationAddress == oldAddress!.value) {
final address = Address(
walletId: _walletId,
value: notificationAddress,
publicKey: [],
derivationIndex: 0,
type: oldAddress.type,
subType: AddressSubType.paynymNotification,
otherData: await storeCode(code.toString()),
);
await _db.updateAddress(oldAddress, address);
}
}
}
}
} }
Future<void> restoreAllHistory({ Future<void> restoreAllHistory({
required int maxUnusedAddressGap, required int maxUnusedAddressGap,
required int maxNumberOfIndexesToCheck, required int maxNumberOfIndexesToCheck,
required Set<String> paymentCodeStrings,
}) async { }) async {
final codes = await getAllPaymentCodesFromNotificationTransactions(); final codes = await getAllPaymentCodesFromNotificationTransactions();
final List<PaymentCode> extraCodes = [];
for (final codeString in paymentCodeStrings) {
if (codes.where((e) => e.toString() == codeString).isEmpty) {
final extraCode = PaymentCode.fromPaymentCode(codeString, _network);
if (extraCode.isValid()) {
extraCodes.add(extraCode);
}
}
}
codes.addAll(extraCodes);
final List<Future<void>> futures = []; final List<Future<void>> futures = [];
for (final code in codes) { for (final code in codes) {
futures.add(restoreHistoryWith( futures.add(
code, maxUnusedAddressGap, maxNumberOfIndexesToCheck)); restoreHistoryWith(
code,
maxUnusedAddressGap,
maxNumberOfIndexesToCheck,
),
);
} }
await Future.wait(futures); await Future.wait(futures);