From 0977711b7a3190d75939711da1f8202c1eaf58c3 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 4 Mar 2024 10:34:46 -0800 Subject: [PATCH] fiat api fixes --- cw_bitcoin/lib/electrum_wallet.dart | 31 +++--- .../lib/lightning_transaction_info.dart | 99 ++++--------------- cw_lightning/lib/lightning_wallet.dart | 43 ++++---- lib/reactions/fiat_rate_update.dart | 9 +- .../dashboard/balance_view_model.dart | 4 +- 5 files changed, 58 insertions(+), 128 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 9c786356c..b46624522 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -46,8 +46,8 @@ part 'electrum_wallet.g.dart'; class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet; -abstract class ElectrumWalletBase - extends WalletBase with Store { +abstract class ElectrumWalletBase + extends WalletBase with Store { ElectrumWalletBase( {required String password, required WalletInfo walletInfo, @@ -55,14 +55,15 @@ abstract class ElectrumWalletBase required this.networkType, required this.mnemonic, required Uint8List seedBytes, - required T Function({ + required BalanceT Function({ required int confirmed, required int unconfirmed, required int frozen, }) this.balanceFactory, + // required TxInfoT Function(Map json) TxInfoFactory, List? initialAddresses, ElectrumClient? electrumClient, - T? initialBalance, + BalanceT? initialBalance, CryptoCurrency? currency}) : hd = currency == CryptoCurrency.bch ? bitcoinCashHDWallet(seedBytes) @@ -74,7 +75,7 @@ abstract class ElectrumWalletBase isEnabledAutoGenerateSubaddress = true, unspentCoins = [], _scripthashesUpdateSubject = {}, - balance = ObservableMap.of( + balance = ObservableMap.of( currency != null ? {currency: initialBalance ?? balanceFactory(confirmed: 0, unconfirmed: 0, frozen: 0)} : {}), this.unspentCoinsInfo = unspentCoinsInfo, this.network = networkType == bitcoin.bitcoin @@ -97,7 +98,7 @@ abstract class ElectrumWalletBase final bitcoin.HDWallet hd; final String mnemonic; - final T Function({ + final BalanceT Function({ required int confirmed, required int unconfirmed, required int frozen, @@ -115,7 +116,7 @@ abstract class ElectrumWalletBase @override @observable - late ObservableMap balance; + late ObservableMap balance; @override @observable @@ -645,7 +646,7 @@ abstract class ElectrumWalletBase ins: ins, time: time, confirmations: confirmations, height: height); } - Future fetchTransactionInfo( + Future fetchTransactionInfo( {required String hash, required int height, required Set myAddresses, @@ -653,7 +654,7 @@ abstract class ElectrumWalletBase try { return ElectrumTransactionInfo.fromElectrumBundle( await getTransactionExpanded(hash: hash, height: height), walletInfo.type, network, - addresses: myAddresses, height: height); + addresses: myAddresses, height: height) as TxInfoT; } catch (e) { if (e is FormatException && retryOnFailure == true) { await Future.delayed(const Duration(seconds: 2)); @@ -664,9 +665,9 @@ abstract class ElectrumWalletBase } @override - Future> fetchTransactions() async { + Future> fetchTransactions() async { try { - final Map historiesWithDetails = {}; + final Map historiesWithDetails = {}; final addressesSet = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); final currentHeight = await electrumClient.getCurrentBlockChainTip() ?? 0; @@ -706,10 +707,10 @@ abstract class ElectrumWalletBase } } - Future> _fetchAddressHistory( + Future> _fetchAddressHistory( BitcoinAddressRecord addressRecord, Set addressesSet, int currentHeight) async { try { - final Map historiesWithDetails = {}; + final Map historiesWithDetails = {}; final history = await electrumClient .getHistory(addressRecord.scriptHash ?? addressRecord.updateScriptHash(network)); @@ -730,7 +731,7 @@ abstract class ElectrumWalletBase storedTx.isPending = storedTx.confirmations == 0; } - historiesWithDetails[txid] = storedTx; + historiesWithDetails[txid] = storedTx as TxInfoT; } else { final tx = await fetchTransactionInfo( hash: txid, height: height, myAddresses: addressesSet, retryOnFailure: true); @@ -794,7 +795,7 @@ abstract class ElectrumWalletBase }); } - Future _fetchBalances() async { + Future _fetchBalances() async { final addresses = walletAddresses.allAddresses.toList(); final balanceFutures = >>[]; for (var i = 0; i < addresses.length; i++) { diff --git a/cw_lightning/lib/lightning_transaction_info.dart b/cw_lightning/lib/lightning_transaction_info.dart index 8129b55d0..20e0f22bc 100644 --- a/cw_lightning/lib/lightning_transaction_info.dart +++ b/cw_lightning/lib/lightning_transaction_info.dart @@ -1,78 +1,28 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; +import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/format_amount.dart'; import 'package:cw_core/wallet_type.dart'; -class LightningTransactionInfo extends TransactionInfo { - LightningTransactionInfo( - this.type, { +class LightningTransactionInfo extends ElectrumTransactionInfo { + LightningTransactionInfo({ required String id, required int amount, int? fee, required TransactionDirection direction, required bool isPending, required DateTime date, - }) { - this.id = id; - this.amount = amount; - this.fee = fee; - this.direction = direction; - this.date = date; - this.isPending = isPending; - } - - factory LightningTransactionInfo.fromHexAndHeader(WalletType type, String hex, - {List? addresses, required int height, int? timestamp, required int confirmations}) { - final tx = bitcoin.Transaction.fromHex(hex); - var exist = false; - var amount = 0; - - if (addresses != null) { - tx.outs.forEach((out) { - try { - final p2pkh = - bitcoin.P2PKH(data: PaymentData(output: out.script), network: bitcoin.bitcoin); - exist = addresses.contains(p2pkh.data.address); - - if (exist) { - amount += out.value!; - } - } catch (_) {} - }); - } - - final date = - timestamp != null ? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000) : DateTime.now(); - - return LightningTransactionInfo( - type, - id: tx.getId(), - isPending: false, - fee: null, - direction: TransactionDirection.incoming, - amount: amount, - date: date, - ); - } - - factory LightningTransactionInfo.fromJson(Map data, WalletType type) { - return LightningTransactionInfo( - type, - id: data['id'] as String, - amount: data['amount'] as int, - fee: data['fee'] as int, - direction: parseTransactionDirectionFromInt(data['direction'] as int), - date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int), - isPending: data['isPending'] as bool, - ); - } - - final WalletType type; - - String? _fiatAmount; + }) : super( + WalletType.lightning, + amount: amount, + fee: fee, + direction: direction, + date: date, + isPending: isPending, + id: id, + confirmations: 0, + height: 0, + ) {} @override String amountFormatted() => @@ -83,21 +33,14 @@ class LightningTransactionInfo extends TransactionInfo { ? '${formatAmount(bitcoinAmountToLightningString(amount: fee!))} ${walletTypeToCryptoCurrency(type).title}' : ''; - @override - String fiatAmount() => _fiatAmount ?? ''; - - @override - void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); - - LightningTransactionInfo updated(LightningTransactionInfo info) { + factory LightningTransactionInfo.fromJson(Map data, WalletType type) { return LightningTransactionInfo( - info.type, - id: id, - amount: info.amount, - fee: info.fee, - direction: direction, - date: date, - isPending: isPending, + id: data['id'] as String, + amount: data['amount'] as int, + fee: data['fee'] as int, + direction: parseTransactionDirectionFromInt(data['direction'] as int), + date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int), + isPending: data['isPending'] as bool, ); } diff --git a/cw_lightning/lib/lightning_wallet.dart b/cw_lightning/lib/lightning_wallet.dart index 88217c136..90c949e2c 100644 --- a/cw_lightning/lib/lightning_wallet.dart +++ b/cw_lightning/lib/lightning_wallet.dart @@ -6,23 +6,16 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:breez_sdk/breez_sdk.dart'; import 'package:breez_sdk/bridge_generated.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; -import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; -import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; -import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/electrum_wallet_snapshot.dart'; -import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/sync_status.dart'; import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/utils/file.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:cw_lightning/lightning_balance.dart'; import 'package:cw_lightning/lightning_transaction_history.dart'; import 'package:cw_lightning/lightning_transaction_info.dart'; @@ -35,7 +28,6 @@ import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart'; import 'package:path_provider/path_provider.dart'; import 'package:cw_lightning/.secrets.g.dart' as secrets; -import 'package:cw_core/wallet_base.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; part 'lightning_wallet.g.dart'; @@ -51,13 +43,10 @@ ElectrumBalance myBalanceFactory( ); } -abstract class LightningWalletBase extends ElectrumWalletBase with Store { +abstract class LightningWalletBase + extends ElectrumWalletBase with Store { bool _isTransactionUpdating; - // @override - // @observable - // ObservableMap lnbalance; - @override @observable SyncStatus syncStatus; @@ -86,7 +75,8 @@ abstract class LightningWalletBase extends ElectrumWalletBase seedBytes: seedBytes, currency: CryptoCurrency.btcln, // balanceFactory: myBalanceFactory, - balanceFactory: ({required int confirmed, required int unconfirmed, required int frozen}) { + balanceFactory: ( + {required int confirmed, required int unconfirmed, required int frozen}) { return LightningBalance( confirmed: 0, unconfirmed: 0, @@ -155,7 +145,11 @@ abstract class LightningWalletBase extends ElectrumWalletBase walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, initialAddresses: snp.addresses, - initialBalance: snp.balance as LightningBalance?, + initialBalance: LightningBalance( + confirmed: snp.balance.confirmed, + unconfirmed: snp.balance.unconfirmed, + frozen: snp.balance.frozen, + ), seedBytes: await mnemonicToSeedBytes(snp.mnemonic), initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex, @@ -164,10 +158,11 @@ abstract class LightningWalletBase extends ElectrumWalletBase } Future setupBreez(Uint8List seedBytes) async { - // Initialize SDK logs listener - final sdk = BreezSDK(); + final sdk = await BreezSDK(); try { - sdk.initialize(); + if (!(await sdk.isInitialized())) { + sdk.initialize(); + } } catch (e) { print("Error initializing Breez: $e"); } @@ -275,32 +270,28 @@ abstract class LightningWalletBase extends ElectrumWalletBase } } - Map convertToTxInfo(List payments) { - Map transactions = {}; + Map convertToTxInfo(List payments) { + Map transactions = {}; for (Payment tx in payments) { if (tx.paymentType == PaymentType.ClosedChannel) { continue; } bool isSend = tx.paymentType == PaymentType.Sent; - transactions[tx.id] = ElectrumTransactionInfo( - WalletType.lightning, + transactions[tx.id] = LightningTransactionInfo( isPending: false, id: tx.id, amount: tx.amountMsat ~/ 1000, fee: tx.feeMsat ~/ 1000, date: DateTime.fromMillisecondsSinceEpoch(tx.paymentTime * 1000), direction: isSend ? TransactionDirection.outgoing : TransactionDirection.incoming, - // N/A for lightning: - height: 0, - confirmations: 0, ); } return transactions; } @override - Future> fetchTransactions() async { + Future> fetchTransactions() async { final sdk = await BreezSDK(); final payments = await sdk.listPayments(req: ListPaymentsRequest()); diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index dcef466d7..05995bb8f 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -29,12 +29,6 @@ Future startFiatRateUpdate( if (appStore.wallet!.type == WalletType.haven) { await updateHavenRate(fiatConversionStore); - } else { - fiatConversionStore.prices[appStore.wallet!.currency] = - await FiatConversionService.fetchPrice( - crypto: appStore.wallet!.currency, - fiat: settingsStore.fiatCurrency, - torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly); } Iterable? currencies; @@ -68,7 +62,8 @@ Future startFiatRateUpdate( } } - // keep btcln price in sync with btc: + // keep btcln price in sync with btc (since the fiat api only returns btc and not btcln) + // (btcln price is just the btc price divided by 100000000) fiatConversionStore.prices[CryptoCurrency.btcln] = (fiatConversionStore.prices[CryptoCurrency.btc] ?? 0) / 100000000; } catch (e) { diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index ea41e427a..1bf59e028 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -63,7 +63,7 @@ abstract class BalanceViewModelBase with Store { @computed double get price { CryptoCurrency currency = appStore.wallet!.currency; - + final price = fiatConvertationStore.prices[currency]; if (price == null) { @@ -392,7 +392,7 @@ abstract class BalanceViewModelBase with Store { } String _getFiatBalance({required double price, String? cryptoAmount}) { - cryptoAmount = cryptoAmount?.replaceAll(',', ''); + cryptoAmount = cryptoAmount?.replaceAll(',', '');// fix for amounts > 1000 if (cryptoAmount == null || cryptoAmount.isEmpty || double.tryParse(cryptoAmount) == null) { return '0.00'; }