fix fiat api issues

This commit is contained in:
Matthew Fosse 2024-03-01 09:55:44 -08:00
parent 27add70e61
commit f80e3bdcc9
8 changed files with 192 additions and 168 deletions

View file

@ -7,23 +7,21 @@ import 'package:cw_core/format_amount.dart';
import 'package:cw_core/wallet_type.dart';
class LightningTransactionInfo extends TransactionInfo {
LightningTransactionInfo(this.type,
{required String id,
required int height,
required int amount,
int? fee,
required TransactionDirection direction,
required bool isPending,
required DateTime date,
required int confirmations}) {
LightningTransactionInfo(
this.type, {
required String id,
required int amount,
int? fee,
required TransactionDirection direction,
required bool isPending,
required DateTime date,
}) {
this.id = id;
this.height = height;
this.amount = amount;
this.fee = fee;
this.direction = direction;
this.date = date;
this.isPending = isPending;
this.confirmations = confirmations;
}
factory LightningTransactionInfo.fromHexAndHeader(WalletType type, String hex,
@ -35,8 +33,8 @@ class LightningTransactionInfo extends TransactionInfo {
if (addresses != null) {
tx.outs.forEach((out) {
try {
final p2pkh = bitcoin.P2PKH(
data: PaymentData(output: out.script), network: bitcoin.bitcoin);
final p2pkh =
bitcoin.P2PKH(data: PaymentData(output: out.script), network: bitcoin.bitcoin);
exist = addresses.contains(p2pkh.data.address);
if (exist) {
@ -46,32 +44,30 @@ class LightningTransactionInfo extends TransactionInfo {
});
}
final date = timestamp != null
? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000)
: DateTime.now();
final date =
timestamp != null ? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000) : DateTime.now();
return LightningTransactionInfo(type,
id: tx.getId(),
height: height,
isPending: false,
fee: null,
direction: TransactionDirection.incoming,
amount: amount,
date: date,
confirmations: confirmations);
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,
height: data['height'] as int,
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,
confirmations: data['confirmations'] as int);
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;
@ -94,26 +90,24 @@ class LightningTransactionInfo extends TransactionInfo {
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
LightningTransactionInfo updated(LightningTransactionInfo info) {
return LightningTransactionInfo(info.type,
id: id,
height: info.height,
amount: info.amount,
fee: info.fee,
direction: direction,
date: date,
isPending: isPending,
confirmations: info.confirmations);
return LightningTransactionInfo(
info.type,
id: id,
amount: info.amount,
fee: info.fee,
direction: direction,
date: date,
isPending: isPending,
);
}
Map<String, dynamic> toJson() {
final m = <String, dynamic>{};
m['id'] = id;
m['height'] = height;
m['amount'] = amount;
m['direction'] = direction.index;
m['date'] = date.millisecondsSinceEpoch;
m['isPending'] = isPending;
m['confirmations'] = confirmations;
m['fee'] = fee;
return m;
}

View file

@ -300,11 +300,9 @@ abstract class LightningWalletBase
isPending: false,
id: tx.id,
amount: tx.amountMsat ~/ 1000,
fee: tx.feeMsat,
fee: tx.feeMsat ~/ 1000,
date: DateTime.fromMillisecondsSinceEpoch(tx.paymentTime * 1000),
height: tx.paymentTime,
direction: isSend ? TransactionDirection.outgoing : TransactionDirection.incoming,
confirmations: 1,
);
}
return transactions;

View file

@ -1,79 +1,78 @@
part of 'lightning.dart';
class CWLightning extends Lightning {
@override
WalletCredentials createLightningRestoreWalletFromSeedCredentials(
{required String name, required String mnemonic, required String password}) =>
BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password);
@override
WalletCredentials createLightningRestoreWalletFromSeedCredentials({
required String name,
required String mnemonic,
required String password})
=> BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password);
@override
WalletCredentials createLightningRestoreWalletFromWIFCredentials(
{required String name,
required String password,
required String wif,
WalletInfo? walletInfo}) =>
BitcoinRestoreWalletFromWIFCredentials(
name: name, password: password, wif: wif, walletInfo: walletInfo);
@override
WalletCredentials createLightningRestoreWalletFromWIFCredentials({
required String name,
required String password,
required String wif,
WalletInfo? walletInfo})
=> BitcoinRestoreWalletFromWIFCredentials(name: name, password: password, wif: wif, walletInfo: walletInfo);
@override
WalletCredentials createLightningNewWalletCredentials({
required String name,
WalletInfo? walletInfo})
=> BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo);
@override
WalletCredentials createLightningNewWalletCredentials(
{required String name, WalletInfo? walletInfo}) =>
BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo);
@override
List<String> getWordList() => wordlist;
@override
List<String> getWordList() => wordlist;
@override
Map<String, String> getWalletKeys(Object wallet) {
final lightningWallet = wallet as ElectrumWallet;
final keys = lightningWallet.keys;
return <String, String>{
'wif': keys.wif,
'privateKey': keys.privateKey,
'publicKey': keys.publicKey
};
}
@override
Map<String, String> getWalletKeys(Object wallet) {
final lightningWallet = wallet as ElectrumWallet;
final keys = lightningWallet.keys;
@override
Future<void> generateNewAddress(Object wallet, String label) async {
final lightningWallet = wallet as ElectrumWallet;
await lightningWallet.walletAddresses.generateNewAddress(label: label);
await wallet.save();
}
return <String, String>{
'wif': keys.wif,
'privateKey': keys.privateKey,
'publicKey': keys.publicKey
};
}
@override
Future<void> updateAddress(Object wallet,String address, String label) async {
final lightningWallet = wallet as ElectrumWallet;
lightningWallet.walletAddresses.updateAddress(address, label);
await wallet.save();
}
@override
Object createLightningTransactionCredentials(List<Output> outputs, {required TransactionPriority priority, int? feeRate})
=> BitcoinTransactionCredentials(
outputs.map((out) => OutputInfo(
fiatAmount: out.fiatAmount,
cryptoAmount: out.cryptoAmount,
address: out.address,
note: out.note,
sendAll: out.sendAll,
extractedAddress: out.extractedAddress,
isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount))
.toList(),
priority: priority as BitcoinTransactionPriority,
feeRate: feeRate);
@override
Future<void> generateNewAddress(Object wallet, String label) async {
final lightningWallet = wallet as ElectrumWallet;
await lightningWallet.walletAddresses.generateNewAddress(label: label);
await wallet.save();
}
@override
Object createLightningTransactionCredentialsRaw(List<OutputInfo> outputs, {TransactionPriority? priority, required int feeRate})
=> BitcoinTransactionCredentials(
outputs,
priority: priority != null ? priority as BitcoinTransactionPriority : null,
feeRate: feeRate);
@override
Future<void> updateAddress(Object wallet, String address, String label) async {
final lightningWallet = wallet as ElectrumWallet;
lightningWallet.walletAddresses.updateAddress(address, label);
await wallet.save();
}
@override
Object createLightningTransactionCredentials(List<Output> outputs,
{required TransactionPriority priority, int? feeRate}) =>
BitcoinTransactionCredentials(
outputs
.map((out) => OutputInfo(
fiatAmount: out.fiatAmount,
cryptoAmount: out.cryptoAmount,
address: out.address,
note: out.note,
sendAll: out.sendAll,
extractedAddress: out.extractedAddress,
isParsedAddress: out.isParsedAddress,
formattedCryptoAmount: out.formattedCryptoAmount))
.toList(),
priority: priority as BitcoinTransactionPriority,
feeRate: feeRate);
@override
Object createLightningTransactionCredentialsRaw(List<OutputInfo> outputs,
{TransactionPriority? priority, required int feeRate}) =>
BitcoinTransactionCredentials(outputs,
priority: priority != null ? priority as BitcoinTransactionPriority : null,
feeRate: feeRate);
@override
List<String> getAddresses(Object wallet) {
@ -98,39 +97,40 @@ class CWLightning extends Lightning {
.toList();
}
@override
String getAddress(Object wallet) {
final lightningWallet = wallet as ElectrumWallet;
return lightningWallet.walletAddresses.address;
}
@override
String formatterLightningAmountToString({required int amount})
=> bitcoinAmountToString(amount: amount);
@override
double formatterLightningAmountToDouble({required int amount})
=> bitcoinAmountToDouble(amount: amount);
@override
int formatterStringDoubleToLightningAmount(String amount)
=> stringDoubleToBitcoinAmount(amount);
@override
List<BitcoinUnspent> getUnspents(Object wallet) {
final lightningWallet = wallet as ElectrumWallet;
return lightningWallet.unspentCoins;
}
Future<void> updateUnspents(Object wallet) async {
final lightningWallet = wallet as ElectrumWallet;
await lightningWallet.updateUnspent();
}
WalletService createLightningWalletService(Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
return LightningWalletService(walletInfoSource, unspentCoinSource);
}
@override
String getAddress(Object wallet) {
final lightningWallet = wallet as ElectrumWallet;
return lightningWallet.walletAddresses.address;
}
@override
List<LightningReceivePageOption> getLightningReceivePageOptions() => LightningReceivePageOption.all;
}
String formatterLightningAmountToString({required int amount}) =>
bitcoinAmountToString(amount: amount * 100000000);
@override
double formatterLightningAmountToDouble({required int amount}) =>
bitcoinAmountToDouble(amount: amount * 100000000);
@override
int formatterStringDoubleToLightningAmount(String amount) => stringDoubleToBitcoinAmount(amount * 100000000);
@override
List<BitcoinUnspent> getUnspents(Object wallet) {
final lightningWallet = wallet as ElectrumWallet;
return lightningWallet.unspentCoins;
}
Future<void> updateUnspents(Object wallet) async {
final lightningWallet = wallet as ElectrumWallet;
await lightningWallet.updateUnspent();
}
WalletService createLightningWalletService(
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
return LightningWalletService(walletInfoSource, unspentCoinSource);
}
@override
List<LightningReceivePageOption> getLightningReceivePageOptions() =>
LightningReceivePageOption.all;
}

View file

@ -339,19 +339,19 @@ class BalanceRowWidget extends StatelessWidget {
height: 40,
width: 40,
displayOnError: Container(
height: 30.0,
width: 30.0,
child: Center(
child: Text(
currency.title.substring(0, min(currency.title.length, 2)),
style: TextStyle(fontSize: 11),
),
),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.shade400,
),
height: 30.0,
width: 30.0,
child: Center(
child: Text(
currency.title.substring(0, min(currency.title.length, 2)),
style: TextStyle(fontSize: 11),
),
),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.shade400,
),
),
),
const SizedBox(height: 10),
Text(
@ -410,9 +410,7 @@ class BalanceRowWidget extends StatelessWidget {
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.extension<BalancePageTheme>()!
.balanceAmountColor,
color: Theme.of(context).extension<BalancePageTheme>()!.balanceAmountColor,
height: 1,
),
maxLines: 1,

View file

@ -96,7 +96,7 @@ class WalletListBody extends StatefulWidget {
class WalletListBodyState extends State<WalletListBody> {
final moneroIcon = Image.asset('assets/images/monero_logo.png', height: 24, width: 24);
final bitcoinIcon = Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
final lightningIcon = Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
final lightningIcon = Image.asset('assets/images/lightning_logo.png', height: 24, width: 24);
final litecoinIcon = Image.asset('assets/images/litecoin_icon.png', height: 24, width: 24);
final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24);
final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);

View file

@ -62,7 +62,14 @@ abstract class BalanceViewModelBase with Store {
@computed
double get price {
final price = fiatConvertationStore.prices[appStore.wallet!.currency];
CryptoCurrency currency = appStore.wallet!.currency;
// the fiat api doesn't correctly get the price of BTCLN
// (as it should just grab the price of BTC)
if (currency == CryptoCurrency.btcln) {
currency = CryptoCurrency.btc;
}
final price = fiatConvertationStore.prices[currency];
if (price == null) {
// price should update on next fetch:
@ -242,6 +249,11 @@ abstract class BalanceViewModelBase with Store {
asset: key,
formattedAssetTitle: _formatterAsset(key)));
}
// get price of btc because btcln is not supported by the fiat api:
if (key == CryptoCurrency.btcln) {
key = CryptoCurrency.btc;
}
final fiatCurrency = settingsStore.fiatCurrency;
final price = fiatConvertationStore.prices[key] ?? 0;
@ -255,7 +267,7 @@ abstract class BalanceViewModelBase with Store {
' ' +
_getFiatBalance(price: price, cryptoAmount: value.formattedAdditionalBalance));
final availableFiatBalance = isFiatDisabled
var availableFiatBalance = isFiatDisabled
? ''
: (fiatCurrency.toString() +
' ' +
@ -389,6 +401,7 @@ abstract class BalanceViewModelBase with Store {
}
String _getFiatBalance({required double price, String? cryptoAmount}) {
cryptoAmount = cryptoAmount?.replaceAll(',', '');
if (cryptoAmount == null || cryptoAmount.isEmpty || double.tryParse(cryptoAmount) == null) {
return '0.00';
}

View file

@ -2,6 +2,7 @@ import 'package:cake_wallet/entities/balance_display_mode.dart';
import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/lightning/lightning.dart';
import 'package:cake_wallet/nano/nano.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/solana/solana.dart';
@ -74,6 +75,10 @@ class TransactionListItem extends ActionListItem with Keyable {
break;
case WalletType.bitcoin:
case WalletType.lightning:
amount = calculateFiatAmountRaw(
cryptoAmount: lightning!.formatterLightningAmountToDouble(amount: transaction.amount),
price: price);
break;
case WalletType.litecoin:
case WalletType.bitcoinCash:
amount = calculateFiatAmountRaw(

View file

@ -42,6 +42,9 @@ abstract class TransactionDetailsViewModelBase with Store {
case WalletType.bitcoinCash:
_addElectrumListItems(tx, dateFormat);
break;
case WalletType.lightning:
_addLightningListItems(tx, dateFormat);
break;
case WalletType.haven:
_addHavenListItems(tx, dateFormat);
break;
@ -223,6 +226,19 @@ abstract class TransactionDetailsViewModelBase with Store {
items.addAll(_items);
}
void _addLightningListItems(TransactionInfo tx, DateFormat dateFormat) {
final _items = [
StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
StandartListItem(
title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
if (tx.feeFormatted()?.isNotEmpty ?? false)
StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
];
items.addAll(_items);
}
void _addHavenListItems(TransactionInfo tx, DateFormat dateFormat) {
items.addAll([
StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),