mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 11:59:30 +00:00
paynym refactor to tx v2
This commit is contained in:
parent
e9300c9208
commit
a69b4f8ed5
10 changed files with 220 additions and 128 deletions
|
@ -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'
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(" ");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue