fiat api fixes

This commit is contained in:
Matthew Fosse 2024-03-04 10:34:46 -08:00
parent 5ad0aa42fb
commit 0977711b7a
5 changed files with 58 additions and 128 deletions

View file

@ -46,8 +46,8 @@ part 'electrum_wallet.g.dart';
class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet;
abstract class ElectrumWalletBase<T extends ElectrumBalance>
extends WalletBase<T, ElectrumTransactionHistory, ElectrumTransactionInfo> with Store {
abstract class ElectrumWalletBase<BalanceT extends ElectrumBalance, TxInfoT extends ElectrumTransactionInfo>
extends WalletBase<BalanceT, ElectrumTransactionHistory, TxInfoT> with Store {
ElectrumWalletBase(
{required String password,
required WalletInfo walletInfo,
@ -55,14 +55,15 @@ abstract class ElectrumWalletBase<T extends ElectrumBalance>
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<String, dynamic> json) TxInfoFactory,
List<BitcoinAddressRecord>? initialAddresses,
ElectrumClient? electrumClient,
T? initialBalance,
BalanceT? initialBalance,
CryptoCurrency? currency})
: hd = currency == CryptoCurrency.bch
? bitcoinCashHDWallet(seedBytes)
@ -74,7 +75,7 @@ abstract class ElectrumWalletBase<T extends ElectrumBalance>
isEnabledAutoGenerateSubaddress = true,
unspentCoins = [],
_scripthashesUpdateSubject = {},
balance = ObservableMap<CryptoCurrency, T>.of(
balance = ObservableMap<CryptoCurrency, BalanceT>.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<T extends ElectrumBalance>
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<T extends ElectrumBalance>
@override
@observable
late ObservableMap<CryptoCurrency, T> balance;
late ObservableMap<CryptoCurrency, BalanceT> balance;
@override
@observable
@ -645,7 +646,7 @@ abstract class ElectrumWalletBase<T extends ElectrumBalance>
ins: ins, time: time, confirmations: confirmations, height: height);
}
Future<ElectrumTransactionInfo?> fetchTransactionInfo(
Future<TxInfoT?> fetchTransactionInfo(
{required String hash,
required int height,
required Set<String> myAddresses,
@ -653,7 +654,7 @@ abstract class ElectrumWalletBase<T extends ElectrumBalance>
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<T extends ElectrumBalance>
}
@override
Future<Map<String, ElectrumTransactionInfo>> fetchTransactions() async {
Future<Map<String, TxInfoT>> fetchTransactions() async {
try {
final Map<String, ElectrumTransactionInfo> historiesWithDetails = {};
final Map<String, TxInfoT> historiesWithDetails = {};
final addressesSet = walletAddresses.allAddresses.map((addr) => addr.address).toSet();
final currentHeight = await electrumClient.getCurrentBlockChainTip() ?? 0;
@ -706,10 +707,10 @@ abstract class ElectrumWalletBase<T extends ElectrumBalance>
}
}
Future<Map<String, ElectrumTransactionInfo>> _fetchAddressHistory(
Future<Map<String, TxInfoT>> _fetchAddressHistory(
BitcoinAddressRecord addressRecord, Set<String> addressesSet, int currentHeight) async {
try {
final Map<String, ElectrumTransactionInfo> historiesWithDetails = {};
final Map<String, TxInfoT> historiesWithDetails = {};
final history = await electrumClient
.getHistory(addressRecord.scriptHash ?? addressRecord.updateScriptHash(network));
@ -730,7 +731,7 @@ abstract class ElectrumWalletBase<T extends ElectrumBalance>
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<T extends ElectrumBalance>
});
}
Future<T> _fetchBalances() async {
Future<BalanceT> _fetchBalances() async {
final addresses = walletAddresses.allAddresses.toList();
final balanceFutures = <Future<Map<String, dynamic>>>[];
for (var i = 0; i < addresses.length; i++) {

View file

@ -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<String>? 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<String, dynamic> 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<String, dynamic> 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,
);
}

View file

@ -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<LightningBalance> with Store {
abstract class LightningWalletBase
extends ElectrumWalletBase<LightningBalance, LightningTransactionInfo> with Store {
bool _isTransactionUpdating;
// @override
// @observable
// ObservableMap<CryptoCurrency, LightningBalance> lnbalance;
@override
@observable
SyncStatus syncStatus;
@ -86,7 +75,8 @@ abstract class LightningWalletBase extends ElectrumWalletBase<LightningBalance>
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<LightningBalance>
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<LightningBalance>
}
Future<void> 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<LightningBalance>
}
}
Map<String, ElectrumTransactionInfo> convertToTxInfo(List<Payment> payments) {
Map<String, ElectrumTransactionInfo> transactions = {};
Map<String, LightningTransactionInfo> convertToTxInfo(List<Payment> payments) {
Map<String, LightningTransactionInfo> 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<Map<String, ElectrumTransactionInfo>> fetchTransactions() async {
Future<Map<String, LightningTransactionInfo>> fetchTransactions() async {
final sdk = await BreezSDK();
final payments = await sdk.listPayments(req: ListPaymentsRequest());

View file

@ -29,12 +29,6 @@ Future<void> 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<CryptoCurrency>? currencies;
@ -68,7 +62,8 @@ Future<void> 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) {

View file

@ -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';
}