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

View file

@ -749,33 +749,99 @@ mixin PaynymWalletInterface {
.subTypeEqualTo(TransactionSubType.bip47Notification)
.findAll();
List<PaymentCode> unBlindedList = [];
List<PaymentCode> codes = [];
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(
transaction: tx,
myNotificationAddress: myAddress,
);
if (unBlinded != null &&
unBlindedList
.where((e) => e.toString() == unBlinded.toString())
.isEmpty) {
unBlindedList.add(unBlinded);
codes.where((e) => e.toString() == unBlinded.toString()).isEmpty) {
codes.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({
required int maxUnusedAddressGap,
required int maxNumberOfIndexesToCheck,
required Set<String> paymentCodeStrings,
}) async {
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 = [];
for (final code in codes) {
futures.add(restoreHistoryWith(
code, maxUnusedAddressGap, maxNumberOfIndexesToCheck));
futures.add(
restoreHistoryWith(
code,
maxUnusedAddressGap,
maxNumberOfIndexesToCheck,
),
);
}
await Future.wait(futures);