paynym refactor to tx v2

This commit is contained in:
julian 2024-01-13 15:49:29 -06:00
parent e9300c9208
commit a69b4f8ed5
10 changed files with 220 additions and 128 deletions

View file

@ -44,6 +44,7 @@ class OutpointV2 {
@Embedded()
class InputV2 {
late final String? scriptSigHex;
late final String? scriptSigAsm;
late final int? sequence;
late final OutpointV2? outpoint;
late final List<String> addresses;
@ -63,6 +64,7 @@ class InputV2 {
static InputV2 isarCantDoRequiredInDefaultConstructor({
required String? scriptSigHex,
String? scriptSigAsm,
required int? sequence,
required OutpointV2? outpoint,
required List<String> addresses,
@ -74,6 +76,7 @@ class InputV2 {
}) =>
InputV2()
..scriptSigHex = scriptSigHex
..scriptSigAsm = scriptSigAsm
..sequence = sequence
..outpoint = outpoint
..addresses = List.unmodifiable(addresses)
@ -85,6 +88,7 @@ class InputV2 {
InputV2 copyWith({
String? scriptSigHex,
String? scriptSigAsm,
int? sequence,
OutpointV2? outpoint,
List<String>? addresses,
@ -96,6 +100,7 @@ class InputV2 {
}) {
return InputV2.isarCantDoRequiredInDefaultConstructor(
scriptSigHex: scriptSigHex ?? this.scriptSigHex,
scriptSigAsm: scriptSigAsm ?? this.scriptSigAsm,
sequence: sequence ?? this.sequence,
outpoint: outpoint ?? this.outpoint,
addresses: addresses ?? this.addresses,
@ -111,6 +116,7 @@ class InputV2 {
String toString() {
return 'InputV2(\n'
' scriptSigHex: $scriptSigHex,\n'
' scriptSigAsm: $scriptSigAsm,\n'
' sequence: $sequence,\n'
' outpoint: $outpoint,\n'
' addresses: $addresses,\n'

View file

@ -6,6 +6,7 @@ part 'output_v2.g.dart';
@Embedded()
class OutputV2 {
late final String scriptPubKeyHex;
late final String? scriptPubKeyAsm;
late final String valueStringSats;
late final List<String> addresses;
@ -18,24 +19,28 @@ class OutputV2 {
static OutputV2 isarCantDoRequiredInDefaultConstructor({
required String scriptPubKeyHex,
String? scriptPubKeyAsm,
required String valueStringSats,
required List<String> addresses,
required bool walletOwns,
}) =>
OutputV2()
..scriptPubKeyHex = scriptPubKeyHex
..scriptPubKeyAsm = scriptPubKeyAsm
..valueStringSats = valueStringSats
..walletOwns = walletOwns
..addresses = List.unmodifiable(addresses);
OutputV2 copyWith({
String? scriptPubKeyHex,
String? scriptPubKeyAsm,
String? valueStringSats,
List<String>? addresses,
bool? walletOwns,
}) {
return OutputV2.isarCantDoRequiredInDefaultConstructor(
scriptPubKeyHex: scriptPubKeyHex ?? this.scriptPubKeyHex,
scriptPubKeyAsm: scriptPubKeyAsm ?? this.scriptPubKeyAsm,
valueStringSats: valueStringSats ?? this.valueStringSats,
addresses: addresses ?? this.addresses,
walletOwns: walletOwns ?? this.walletOwns,
@ -61,6 +66,7 @@ class OutputV2 {
return OutputV2.isarCantDoRequiredInDefaultConstructor(
scriptPubKeyHex: json["scriptPubKey"]["hex"] as String,
scriptPubKeyAsm: json["scriptPubKey"]["asm"] as String?,
valueStringSats: parseOutputAmountString(
json["value"].toString(),
decimalPlaces: decimalPlaces,
@ -100,27 +106,10 @@ class OutputV2 {
String toString() {
return 'OutputV2(\n'
' scriptPubKeyHex: $scriptPubKeyHex,\n'
' scriptPubKeyAsm: $scriptPubKeyAsm,\n'
' value: $value,\n'
' walletOwns: $walletOwns,\n'
' addresses: $addresses,\n'
')';
}
}
bool _listEquals<T, U>(List<T> a, List<U> b) {
if (T != U) {
return false;
}
if (a.length != b.length) {
return false;
}
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}

View file

@ -11,12 +11,12 @@
import 'dart:typed_data';
import 'package:bip47/src/util.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/output.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
abstract class Bip47Utils {
/// looks at tx outputs and returns a blinded payment code if found
static Uint8List? getBlindedPaymentCodeBytesFrom(Transaction transaction) {
static Uint8List? getBlindedPaymentCodeBytesFrom(TransactionV2 transaction) {
for (int i = 0; i < transaction.outputs.length; i++) {
final bytes = getBlindedPaymentCodeBytesFromOutput(
transaction.outputs.elementAt(i));
@ -28,7 +28,7 @@ abstract class Bip47Utils {
return null;
}
static Uint8List? getBlindedPaymentCodeBytesFromOutput(Output output) {
static Uint8List? getBlindedPaymentCodeBytesFromOutput(OutputV2 output) {
Uint8List? blindedCodeBytes;
List<String>? scriptChunks = output.scriptPubKeyAsm?.split(" ");

View file

@ -6,9 +6,10 @@ import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/crypto_currency/interfaces/paynym_currency_interface.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/bip39_hd_currency.dart';
class Bitcoin extends Bip39HDCurrency {
class Bitcoin extends Bip39HDCurrency with PaynymCurrencyInterface {
Bitcoin(super.network) {
switch (network) {
case CryptoCurrencyNetwork.main:
@ -49,11 +50,6 @@ class Bitcoin extends Bip39HDCurrency {
fractionDigits: fractionDigits,
);
Amount get dustLimitP2PKH => Amount(
rawValue: BigInt.from(546),
fractionDigits: fractionDigits,
);
@override
coinlib.NetworkParams get networkParams {
switch (network) {

View file

@ -0,0 +1,9 @@
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/bip39_hd_currency.dart';
mixin PaynymCurrencyInterface on Bip39HDCurrency {
Amount get dustLimitP2PKH => Amount(
rawValue: BigInt.from(546),
fractionDigits: fractionDigits,
);
}

View file

@ -9,17 +9,18 @@ import 'package:stackwallet/utilities/extensions/extensions.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/crypto_currency/interfaces/paynym_currency_interface.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart';
class BitcoinWallet extends Bip39HDWallet
with ElectrumXInterface, CoinControlInterface, PaynymInterface {
class BitcoinWallet<T extends PaynymCurrencyInterface> extends Bip39HDWallet<T>
with ElectrumXInterface<T>, CoinControlInterface, PaynymInterface<T> {
@override
int get isarTransactionVersion => 2;
BitcoinWallet(CryptoCurrencyNetwork network) : super(Bitcoin(network));
BitcoinWallet(CryptoCurrencyNetwork network) : super(Bitcoin(network) as T);
@override
FilterOperation? get changeAddressFilterOperation =>
@ -153,6 +154,7 @@ class BitcoinWallet extends Bip39HDWallet
InputV2 input = InputV2.isarCantDoRequiredInDefaultConstructor(
scriptSigHex: map["scriptSig"]?["hex"] as String?,
scriptSigAsm: map["scriptSig"]?["asm"] as String?,
sequence: map["sequence"] as int?,
outpoint: outpoint,
valueStringSats: valueStringSats,

View file

@ -19,6 +19,7 @@ import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/paynym_is_api.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
@ -45,6 +46,7 @@ import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/electrumx_int
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/private_key_interface.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
@ -471,6 +473,24 @@ abstract class Wallet<T extends CryptoCurrency> {
),
);
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
final Set<String> codesToCheck = {};
if (this is PaynymInterface) {
// isSegwit does not matter here at all
final myCode =
await (this as PaynymInterface).getPaymentCode(isSegwit: false);
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);
}
}
}
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId));
await updateChainHeight();
@ -505,6 +525,14 @@ abstract class Wallet<T extends CryptoCurrency> {
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.70, walletId));
await fetchFuture;
// TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
if (this is PaynymInterface && codesToCheck.isNotEmpty) {
await (this as PaynymInterface)
.checkForNotificationTransactionsTo(codesToCheck);
// check utxos again for notification outputs
await updateUTXOs();
}
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.80, walletId));
// await getAllTxsToWatch();

View file

@ -1,6 +1,7 @@
import 'package:stackwallet/wallets/crypto_currency/intermediate/bip39_hd_currency.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
mixin CoinControlInterface on Bip39HDWallet {
mixin CoinControlInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
// any required here?
// currently only used to id which wallets support coin control
}

View file

@ -20,12 +20,13 @@ import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/bip39_hd_currency.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart';
import 'package:uuid/uuid.dart';
mixin ElectrumXInterface on Bip39HDWallet {
mixin ElectrumXInterface<T extends Bip39HDCurrency> on Bip39HDWallet<T> {
late ElectrumXClient electrumXClient;
late CachedElectrumXClient electrumXCachedClient;
@ -533,20 +534,29 @@ mixin ElectrumXInterface on Bip39HDWallet {
final address = await mainDB.getAddress(walletId, sd.utxo.address!);
if (address?.derivationPath != null) {
if (address!.subType == AddressSubType.paynymReceive) {
// TODO paynym
// final code = await paymentCodeStringByKey(address.otherData!);
//
// final bip47base = await getBip47BaseNode();
//
// final privateKey = await getPrivateKeyForPaynymReceivingAddress(
// paymentCodeString: code!,
// index: address.derivationIndex,
// );
//
// keys = coinlib.HDPrivateKey.fromKeyAndChainCode(
// privateKey,
// bip47base.chainCode,
// );
if (this is PaynymInterface) {
final code = await (this as PaynymInterface)
.paymentCodeStringByKey(address.otherData!);
final bip47base =
await (this as PaynymInterface).getBip47BaseNode();
final privateKey = await (this as PaynymInterface)
.getPrivateKeyForPaynymReceivingAddress(
paymentCodeString: code!,
index: address.derivationIndex,
);
keys = coinlib.HDPrivateKey.fromKeyAndChainCode(
coinlib.ECPrivateKey.fromHex(privateKey.toHex),
bip47base.chainCode,
);
} else {
throw Exception(
"$runtimeType tried to fetchBuildTxData for a paynym address"
" in a non PaynymInterface wallet",
);
}
} else {
keys = root.derivePath(address.derivationPath!.value);
}

View file

@ -12,6 +12,8 @@ import 'package:isar/isar.dart';
import 'package:pointycastle/digests/sha256.dart';
import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart';
import 'package:stackwallet/exceptions/wallet/paynym_send_exception.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/v2/input_v2.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/signing_data.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
@ -20,6 +22,7 @@ import 'package:stackwallet/utilities/bip47_utils.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/crypto_currency/interfaces/paynym_currency_interface.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart';
@ -43,12 +46,8 @@ String _sendPaynymAddressDerivationPath(
}) =>
"${_basePaynymDerivePath(testnet: testnet)}/0/$index";
mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
Amount get _dustLimitP2PKH => Amount(
rawValue: BigInt.from(546),
fractionDigits: cryptoCurrency.fractionDigits,
);
mixin PaynymInterface<T extends PaynymCurrencyInterface>
on Bip39HDWallet<T>, ElectrumXInterface<T> {
btc_dart.NetworkType get networkType => btc_dart.NetworkType(
messagePrefix: cryptoCurrency.networkParams.messagePrefix,
bech32: cryptoCurrency.networkParams.bech32Hrp,
@ -447,9 +446,7 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
List<UTXO>? utxos,
}) async {
try {
// final amountToSend = cryptoCurrency.dustLimitP2PKH;
final amountToSend = _dustLimitP2PKH;
final amountToSend = cryptoCurrency.dustLimitP2PKH;
final List<UTXO> availableOutputs =
utxos ?? await mainDB.getUTXOs(walletId).findAll();
final List<UTXO> spendableOutputs = [];
@ -550,14 +547,14 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
}
if (satoshisBeingUsed - amountToSend.raw >
feeForNoChange + _dustLimitP2PKH.raw) {
feeForNoChange + cryptoCurrency.dustLimitP2PKH.raw) {
// try to add change output due to "left over" amount being greater than
// the estimated fee + the dust limit
BigInt changeAmount =
satoshisBeingUsed - amountToSend.raw - feeForWithChange;
// check estimates are correct and build notification tx
if (changeAmount >= _dustLimitP2PKH.raw &&
if (changeAmount >= cryptoCurrency.dustLimitP2PKH.raw &&
satoshisBeingUsed - amountToSend.raw - changeAmount ==
feeForWithChange) {
var txn = await _createNotificationTx(
@ -746,7 +743,7 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
txb.addOutput(
notificationAddress,
(overrideAmountForTesting ?? _dustLimitP2PKH.raw).toInt(),
(overrideAmountForTesting ?? cryptoCurrency.dustLimitP2PKH.raw).toInt(),
);
txb.addOutput(opReturnScript, 0);
@ -854,44 +851,67 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
final myNotificationAddress = await getMyNotificationAddress();
final txns = await mainDB
.getTransactions(walletId)
final txns = await mainDB.isar.transactionV2s
.where()
.walletIdEqualTo(walletId)
.filter()
.subTypeEqualTo(TransactionSubType.bip47Notification)
.findAll();
for (final tx in txns) {
if (tx.type == TransactionType.incoming &&
tx.address.value?.value == myNotificationAddress.value) {
final unBlindedPaymentCode = await unBlindedPaymentCodeFromTransaction(
transaction: tx,
);
switch (tx.type) {
case TransactionType.incoming:
for (final output in tx.outputs) {
for (final outputAddress in output.addresses) {
if (outputAddress == myNotificationAddress.value) {
final unBlindedPaymentCode =
await unBlindedPaymentCodeFromTransaction(
transaction: tx,
);
if (unBlindedPaymentCode != null &&
paymentCodeString == unBlindedPaymentCode.toString()) {
// await _setConnectedCache(paymentCodeString, true);
return true;
}
if (unBlindedPaymentCode != null &&
paymentCodeString == unBlindedPaymentCode.toString()) {
// await _setConnectedCache(paymentCodeString, true);
return true;
}
final unBlindedPaymentCodeBad =
await unBlindedPaymentCodeFromTransactionBad(
transaction: tx,
);
final unBlindedPaymentCodeBad =
await unBlindedPaymentCodeFromTransactionBad(
transaction: tx,
);
if (unBlindedPaymentCodeBad != null &&
paymentCodeString == unBlindedPaymentCodeBad.toString()) {
// await _setConnectedCache(paymentCodeString, true);
return true;
}
} else if (tx.type == TransactionType.outgoing) {
if (tx.address.value?.otherData != null) {
final code =
await paymentCodeStringByKey(tx.address.value!.otherData!);
if (code == paymentCodeString) {
// await _setConnectedCache(paymentCodeString, true);
return true;
if (unBlindedPaymentCodeBad != null &&
paymentCodeString == unBlindedPaymentCodeBad.toString()) {
// await _setConnectedCache(paymentCodeString, true);
return true;
}
}
}
}
}
case TransactionType.outgoing:
for (final output in tx.outputs) {
for (final outputAddress in output.addresses) {
final address = await mainDB.isar.addresses
.where()
.walletIdEqualTo(walletId)
.filter()
.subTypeEqualTo(AddressSubType.paynymNotification)
.and()
.valueEqualTo(outputAddress)
.findFirst();
if (address?.otherData != null) {
final code = await paymentCodeStringByKey(address!.otherData!);
if (code == paymentCodeString) {
// await _setConnectedCache(paymentCodeString, true);
return true;
}
}
}
}
default:
break;
}
}
@ -900,7 +920,7 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
return false;
}
Uint8List? _pubKeyFromInput(Input input) {
Uint8List? _pubKeyFromInput(InputV2 input) {
final scriptSigComponents = input.scriptSigAsm?.split(" ") ?? [];
if (scriptSigComponents.length > 1) {
return scriptSigComponents[1].fromHex;
@ -919,7 +939,7 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
}
Future<PaymentCode?> unBlindedPaymentCodeFromTransaction({
required Transaction transaction,
required TransactionV2 transaction,
}) async {
try {
final blindedCodeBytes =
@ -932,8 +952,8 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
final designatedInput = transaction.inputs.first;
final txPoint = designatedInput.txid.fromHex.reversed.toList();
final txPointIndex = designatedInput.vout;
final txPoint = designatedInput.outpoint!.txid.fromHex.reversed.toList();
final txPointIndex = designatedInput.outpoint!.vout;
final rev = Uint8List(txPoint.length + 4);
Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length);
@ -970,7 +990,7 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
}
Future<PaymentCode?> unBlindedPaymentCodeFromTransactionBad({
required Transaction transaction,
required TransactionV2 transaction,
}) async {
try {
final blindedCodeBytes =
@ -983,8 +1003,8 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
final designatedInput = transaction.inputs.first;
final txPoint = designatedInput.txid.fromHex.toList();
final txPointIndex = designatedInput.vout;
final txPoint = designatedInput.outpoint!.txid.fromHex.toList();
final txPointIndex = designatedInput.outpoint!.vout;
final rev = Uint8List(txPoint.length + 4);
Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length);
@ -1022,8 +1042,9 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
Future<List<PaymentCode>>
getAllPaymentCodesFromNotificationTransactions() async {
final txns = await mainDB
.getTransactions(walletId)
final txns = await mainDB.isar.transactionV2s
.where()
.walletIdEqualTo(walletId)
.filter()
.subTypeEqualTo(TransactionSubType.bip47Notification)
.findAll();
@ -1032,18 +1053,33 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
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,
networkType: networkType,
),
);
if (tx.type == TransactionType.outgoing) {
for (final output in tx.outputs) {
for (final outputAddress
in output.addresses.where((e) => e.isNotEmpty)) {
final address = await mainDB.isar.addresses
.where()
.walletIdEqualTo(walletId)
.filter()
.subTypeEqualTo(AddressSubType.paynymNotification)
.and()
.valueEqualTo(outputAddress)
.findFirst();
if (address?.otherData != null) {
final codeString =
await paymentCodeStringByKey(address!.otherData!);
if (codeString != null &&
codes.where((e) => e.toString() == codeString).isEmpty) {
codes.add(
PaymentCode.fromPaymentCode(
codeString,
networkType: networkType,
),
);
}
}
}
}
} else {
// otherwise we need to un blind the code
@ -1072,8 +1108,9 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
Future<void> checkForNotificationTransactionsTo(
Set<String> otherCodeStrings) async {
final sentNotificationTransactions = await mainDB
.getTransactions(walletId)
final sentNotificationTransactions = await mainDB.isar.transactionV2s
.where()
.walletIdEqualTo(walletId)
.filter()
.subTypeEqualTo(TransactionSubType.bip47Notification)
.and()
@ -1087,23 +1124,37 @@ mixin PaynymInterface on Bip39HDWallet, ElectrumXInterface {
}
for (final tx in sentNotificationTransactions) {
if (tx.address.value != null && tx.address.value!.otherData == null) {
final oldAddress =
await mainDB.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,
derivationPath: oldAddress.derivationPath,
type: oldAddress.type,
subType: AddressSubType.paynymNotification,
otherData: await storeCode(code.toString()),
);
await mainDB.updateAddress(oldAddress, address);
for (final output in tx.outputs) {
for (final outputAddress in output.addresses) {
if (outputAddress.isNotEmpty) {
for (final code in codes) {
final notificationAddress = code.notificationAddressP2PKH();
if (outputAddress == notificationAddress) {
Address? storedAddress =
await mainDB.getAddress(walletId, outputAddress);
if (storedAddress == null) {
// most likely not mine
storedAddress = Address(
walletId: walletId,
value: notificationAddress,
publicKey: [],
derivationIndex: 0,
derivationPath: null,
type: AddressType.unknown,
subType: AddressSubType.paynymNotification,
otherData: await storeCode(code.toString()),
);
} else {
storedAddress = storedAddress.copyWith(
subType: AddressSubType.paynymNotification,
otherData: await storeCode(code.toString()),
);
}
await mainDB.updateOrPutAddresses([storedAddress]);
}
}
}
}
}